【python】pandasで異なるdf同士の判定をする

# やりたいこと
df_A

|kome  |gu  |date  |
|---|---|---|
|ササニシキ  |	うめ  |	20210211	|
|ササニシキ  |	たまご  |	20210213	|
|コシヒカリ  |	おかか  |	20210315	|
|コシヒカリ  |	しゃけ  |	20210511	|

df_B

|gu  |santi  |
|---|---|
|うめ|和歌山|
|しゃけ|北海道|
|おかか|鹿児島|
|こんぶ|北海道|
|いくら|北海道|


df_Aとdf_Bを使って、df_Aをこうしたい  

|kome  |gu  |date  |flag|
|---|---|---|---|
|ササニシキ  |	うめ  |	20210211	|    和歌山   |
|ササニシキ  |	たまご  |	20210213	|      |
|コシヒカリ  |	おかか  |	20210315	|   鹿児島   |
|コシヒカリ  |	しゃけ  |	20210511	|   北海道   |


guが一致したらdf_Bの値をdf_Aに追加するイメージ。
 ~~前提としてdf_Aとdf_Bのguは一意なものとします。~~

参考文献はこちら　→　https://note.nkmk.me/python-pandas-where-mask/


# 準備
サンプルを作成します。
おにぎりなのは趣味です。

```python
import pandas as pd
import numpy as np
import time

df_A = pd.DataFrame({'kome': ["ササニシキ", "ササニシキ","コシヒカリ","コシヒカリ"],
                   'gu': ["うめ","たまご","おかか", "しゃけ"],
                   'date': [20210211, 20210213, 20210315, 20210511]})

df_B = pd.DataFrame({'gu': ["うめ", "しゃけ", "おかか","こんぶ","いくら"],
                   'santi': ["和歌山", "北海道", "鹿児島", "北海道", "北海道"]})

```


#  トライ1
whereを使う方法。
あらかじめ空の列を作成する必要があります。

```python
df_A["flag"] = ""
_start = time.time()

for i in range(len(df_B)):
    df_A["flag"].where(df_A["gu"]==df_B.at[i, "gu"],df_B.at[i, "santi"])

# 計測
print(time.time() - _start)
print(df_A)


# 出力結果
# >>> print(time.time() - _start)
# 0.14820408821105957
# >>> print(df_A)
#     kome   gu      date flag
# 0  ササニシキ   うめ  20210211
# 1  ササニシキ  たまご  20210213
# 2  コシヒカリ  おかか  20210315
# 3  コシヒカリ  しゃけ  20210511
```

なぜかうまくいかない。
上書きしないようにしていたのでうまくいかないのは当たり前でした。

が、inplace=Trueにしてもなんか変。


```python
df_A["flag"] = ""
_start = time.time()

for i in range(len(df_B)):
    df_A["flag"].where(df_A["gu"]==df_B.at[i, "gu"],df_B.at[i, "santi"] , inplace=True)

# 計測
print(time.time() - _start)
print(df_A)


# 出力結果
# >>> print(time.time() - _start)
# 0.1444559097290039
# >>> print(df_A)
#     kome   gu      date flag
# 0  ササニシキ   うめ  20210211  北海道
# 1  ササニシキ  たまご  20210213  北海道
# 2  コシヒカリ  おかか  20210315  北海道
# 3  コシヒカリ  しゃけ  20210511  北海道
```

潔くあきらめる。
人生諦めが肝心。


#  トライ2
locを使う方法。
存在しない列を設定してもOK。

```python
_start = time.time()

for i in range(len(df_B)):
    df_A.loc[df_A["gu"] == df_B.at[i, "gu"],'flag'] = df_B.at[i, "santi"]    

# 計測
print(time.time() - _start)
print(df_A)

# 出力結果
# >>> print(time.time() - _start)
# 0.13238096237182617
# >>> print(df_A)
#     kome   gu      date flag
# 0  ササニシキ   うめ  20210211  和歌山
# 1  ササニシキ  たまご  20210213  
# 2  コシヒカリ  おかか  20210315  鹿児島
# 3  コシヒカリ  しゃけ  20210511  北海道

```

うまくいった。
あと微妙にwhereより早めな希ガス。

というわけで採用じゃー！


# トライ3（1/27追記）
コメントいただき、mergeをやってみようと思いました。
実環境のデータは列名不一致＆df_Bが100列相当なので見直し版。
※これはデータが一意な場合の話になります


```python
import pandas as pd
import numpy as np
import time

df_A = pd.DataFrame({'kome': ["ササニシキ", "ササニシキ","コシヒカリ","コシヒカリ"],
                   'gu': ["うめ","たまご","おかか", "しゃけ"],
                   'date': [20210211, 20210213, 20210315, 20210511]})

# 列名の変更とダミー列の追加
df_B = pd.DataFrame({'sozai': ["うめ", "しゃけ", "おかか","こんぶ","いくら"],
                   'santi': ["和歌山", "北海道", "鹿児島", "北海道", "北海道"],
                   'santi2': ["和歌山", "北海道", "鹿児島", "北海道", "北海道"]})

#処理開始
_start = time.time()
df_A = pd.merge(df_A, df_B[["sozai", "santi"]], how="left", left_on="gu", right_on="sozai")
df_A = df_A.drop("sozai",axis=1)

# 計測
print(time.time() - _start)
print(df_A)


# 出力結果
# >>> print(time.time() - _start)
# 0.12956595420837402
# >>> print(df_A)
#     kome   gu      date santi
# 0  ササニシキ   うめ  20210211   和歌山
# 1  ササニシキ  たまご  20210213   NaN
# 2  コシヒカリ  おかか  20210315   鹿児島
# 3  コシヒカリ  しゃけ  20210511   北海道

```

santiに該当する部分は名前共通なのでリネームしなくてもいいかなという。
スマートでよき！

# 1/27追記そのに
なんかおかしいなと思ったら、実環境のデータはキーが一意じゃなかったです。
ので、当方は2の方法を使います……。
確認不足ここに極まれり。