虽然这个问题与Fuzzy Match Merge with Pandas密切相关,但这个问题特别是当一个DataFrame
中的密钥是一个时,合并仅(或在这种情况下为子集)完全匹配,或另一个DataFrame
中密钥的子字符串。为了说明我的观点,这里有2 DataFrames
:
df1
id code
0 1 E282
1 2 O0080
2 3 R52
3 4 J0100
4 5 F99
df2
code val
0 V282 11
1 O008 12
2 J0101 13
3 F99 14
4 R55 15
使用difflib
的问题是我真的不想匹配最接近的字符串,我不确定我是否能够将V282
之类的匹配分隔为{{1 }},这应该不会发生,并且应该合并E282
到O008
之类的匹配。
预期输出应为
O0080
我可以用
来达到这个结果 code1 id
0 O0080 2
1 F99 5
但由于import numpy as np
df1[np.logical_or.reduce([df1['code'].str.contains(code) for code in df2.code.tolist()])]
长42M行而df1
包含~4000个代码,因此此方法速度令人难以置信。这是我要做的最好的事情吗?这看起来很不幸,当内部合并一个21M行df和一个7M行df精确键时,< 1分钟。
答案 0 :(得分:1)
这是一个难题。也许考虑一个python方法? any
会在这里短路,所以你应该节省一些周期。此外,contains
不一定从头开始检查,因此使用startswith
代替应该更有效。
df1[
any(
i.startswith(j) for j in df2.codes.tolist()
) for i in df1.codes.tolist()
]
答案 1 :(得分:1)
那:
import pandas as pd
df1 = pd.DataFrame({'id':[1,2,3,4,5], 'code':['E282', 'O0080', 'R52', 'J0100', 'F99']})
df2 = pd.DataFrame({'code':['V282','O008','J0101','F99','R55'], 'val':[11,12, 13, 14, 15]})
pat = "|".join(df2['code'])
df1.insert(0, 'part_code', df1['code'].str.extract("(" + pat + ')', expand=False))
pd.merge(df1, df2, how='inner', left_on='part_code', right_on='code')[['code_y', 'id']]
的启发