我有 2 个 pandas 数据框,它们都包含公司名称。我想使用模糊匹配将这两个数据框合并到公司名称上。但问题是 1 个数据帧包含 5m 行,另外 1 个数据帧包含大约 10k 行,所以我的模糊匹配需要很长时间才能运行。我想知道有没有什么有效的方法?
这些是我现在正在使用的代码:
def fuzzy_merge(df_1, df_2, key1, key2, threshold=90, limit=2):
"""
:param df_1: the left table to join
:param df_2: the right table to join
:param key1: key column of the left table
:param key2: key column of the right table
:param threshold: how close the matches should be to return a match, based on Levenshtein distance
:param limit: the amount of matches that will get returned, these are sorted high to low
:return: dataframe with boths keys and matches
"""
s = df_2[key2].tolist()
m = df_1[key1].apply(lambda x: process.extract(x, s, limit=limit))
df_1['matches'] = m
m2 = df_1['matches'].apply(lambda x: ', '.join([i[0] for i in x if i[1] >= threshold]))
df_1['matches'] = m2
return df_1
这些是 df1 和 df2 的一些示例数据。
df1
df1_ID | 公司名称 |
---|---|
AB0091 | 苹果 |
AC0092 | 微软 |
df2
df2_ID | 公司名称 |
---|---|
F001ABC | 应用 |
E002ABG | 微观 |
正如您所看到的,公司名称可能包含一些拼写错误和两个数据帧中的差异,并且没有其他列可以用来进行合并,所以这就是为什么我需要对公司名称进行模糊匹配。最终目标是有效地使用公司名称来匹配这两个大型数据框。
谢谢!
一种可能的方法是按以下方式使用
rapidfuzz
和 process.extractOne()
方法:
import pandas as pd
from rapidfuzz import process
data1 = {
'df1_ID': ['AB0091', 'AC0092'],
'Company Name': ['Apple', 'Microsoft']
}
df1 = pd.DataFrame(data1)
data2 = {
'df2_ID': ['F001ABC', 'E002ABG'],
'Company Name': ['Appl', 'The microst']
}
df2 = pd.DataFrame(data2)
def fuzzy_match(row, df2, key, threshold=70):
best_match = process.extractOne(row['Company Name'], df2['Company Name'], score_cutoff=threshold)
if best_match:
matched_id = df2.loc[df2['Company Name'] == best_match[0], 'df2_ID'].values[0]
return pd.Series([best_match[0], matched_id, best_match[1]])
return pd.Series([None, None, None])
df1[['Matched Company', 'Matched df2_ID', 'Match Score']] = df1.apply(fuzzy_match, axis=1, df2=df2, key='Company Name')
print(df1)
将返回:
df1_ID Company Name Matched Company Matched df2_ID Match Score
0 AB0091 Apple Appl F001ABC 88.888889
1 AC0092 Microsoft None None NaN
输出完全取决于您选择的阈值。 90 不匹配任何东西,而 70 匹配 Apple。对于 Microsoft 的匹配,您需要降低 (50),
df1_ID Company Name Matched Company Matched df2_ID Match Score
0 AB0091 Apple Appl F001ABC 88.888889
1 AC0092 Microsoft The microst E002ABG 60.000000
但你可能会在其他事情上得到不合理的匹配: