如何使用fuzzywuzzy高效实现两个pandas dataframe按Name字段模糊匹配拼接
问题原因
- 双重遍历的时间复杂度是O(n*m),n是df的行数,m是df2的行数,假设两个表各有1万行,就要跑1亿次相似度计算,量级上去之后必然极慢。
iterrows本身是pandas里遍历效率最低的方式之一,每次遍历都要做行数据的类型转换,额外增加了大量开销。- 你之前用到的fuzzywuzzy底层是纯Python实现的编辑距离计算,本身运算速度很慢,进一步放大了性能问题。
- 没有做预过滤:所有记录两两全量匹配,大量无意义的相似度计算(比如完全不可能匹配的姓名也跑了一次计算)浪费了绝大多数性能。
优化方案
1. 替换运算库(成本最低,立即可用)
直接把fuzzywuzzy替换为rapidfuzz,接口完全兼容,底层是C++实现,相似度计算速度比fuzzywuzzy快20~100倍,无需修改业务逻辑就能获得明显提速。
2. 加入分块逻辑减少匹配量
先对两个表的姓名做粗粒度分组,只在同组内做相似度计算:比如按姓名的第一个词、姓氏前3个字符、首字母组合等规则分组,排除完全不可能匹配的组合,能直接把运算量降低1~2个数量级,且不会影响匹配准确率。
3. 用批量向量化运算替代循环
不要用iterrows做逐行遍历,直接用rapidfuzz提供的批量匹配接口一次性计算所有相似度,还支持多线程并行:
import pandas as pd from rapidfuzz import fuzz, process df1_name_list = df["Name"].tolist() df2_name_list = df2["Name"].tolist() df2_value_list = df2["value"].tolist() # 批量计算所有姓名对的相似度,自动过滤低于85分的结果,开启多线程 similarity_matrix = process.cdist( df1_name_list, df2_name_list, scorer=fuzz.ratio, score_cutoff=85, workers=-1 ) # 批量赋值匹配结果 for idx, row_scores in enumerate(similarity_matrix): if row_scores.max() >= 85: match_df2_idx = row_scores.argmax() df.loc[idx, "value I want to add to first df"] = df2_value_list[match_df2_idx]
4. 超大数据量优化
如果两个表的行数都超过10万,还可以先把姓名转换为N-gram向量,用Faiss等近似近邻检索库做匹配,性能还能再提升一个量级。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

