一般的なアプローチの場合:fuzzy_merge
わずかに異なる文字列を含む2つのデータフレームの列をマージする、より一般的なシナリオの場合、次の関数は、パンダの機能を模倣するためにdifflib.get_close_matches
と一緒に使用しますが、あいまい一致を使用します。merge
merge
import difflib
def fuzzy_merge(df1, df2, left_on, right_on, how='inner', cutoff=0.6):
df_other= df2.copy()
df_other[left_on] = [get_closest_match(x, df1[left_on], cutoff)
for x in df_other[right_on]]
return df1.merge(df_other, on=left_on, how=how)
def get_closest_match(x, other, cutoff):
matches = difflib.get_close_matches(x, other, cutoff=cutoff)
return matches[0] if matches else None
2つのサンプルデータフレームの使用例を次に示します。
print(df1)
key number
0 one 1
1 two 2
2 three 3
3 four 4
4 five 5
print(df2)
key_close letter
0 three c
1 one a
2 too b
3 fours d
4 a very different string e
上記の例では、次のようになります。
fuzzy_merge(df1, df2, left_on='key', right_on='key_close')
key number key_close letter
0 one 1 one a
1 two 2 too b
2 three 3 three c
3 four 4 fours d
そして、次のように左結合を行うことができます。
fuzzy_merge(df1, df2, left_on='key', right_on='key_close', how='left')
key number key_close letter
0 one 1 one a
1 two 2 too b
2 three 3 three c
3 four 4 fours d
4 five 5 NaN NaN
右結合の場合、左側のデータフレームに一致しないすべてのキーがありますNone
。
fuzzy_merge(df1, df2, left_on='key', right_on='key_close', how='right')
key number key_close letter
0 one 1.0 one a
1 two 2.0 too b
2 three 3.0 three c
3 four 4.0 fours d
4 None NaN a very different string e
また、カットオフ内で一致するアイテムがない場合は、空のリストが返されることに注意してください。共有の例では、最後のインデックスを次のように変更すると、次のようになります。difflib.get_close_matches
df2
print(df2)
letter
one a
too b
three c
fours d
a very different string e
エラーが発生しますindex out of range
:
df2.index.map(lambda x: difflib.get_close_matches(x, df1.index)[0])
IndexError:リストインデックスが範囲外です
これを解決するために、上記の関数は、実際に一致するものが含まれている場合にのみ、get_closest_match
によって返されるリストにインデックスを付けることによって、最も近い一致を返します。difflib.get_close_matches