如何高效实现基于Fuzzy Wuzzy的Pandas单列相似名称统一替换
高效统一相似姓名的实现方案
你当前的逐行循环匹配方法时间复杂度较高(O(n*m),n为数据行数,m为标准名数量),针对2000+行数据,以下是几个更高效的优化方案:
方案1:用RapidFuzz替代FuzzyWuzzy(性能提升最显著)
FuzzyWuzzy是纯Python实现,速度较慢;RapidFuzz是其C语言重写版本,API兼容且性能提升数倍,是首选优化方向。
批量匹配实现
from rapidfuzz import process, fuzz import pandas as pd import numpy as np # 你的标准名称列表 standard_names = ['Andrea Glz', 'Lineth Arce'] # 生成所有姓名与标准名的相似度矩阵(向量化计算,避免逐行循环) similarity_matrix = process.cdist(df['姓名'], standard_names, scorer=fuzz.token_set_ratio) # 找到每个姓名对应的最高相似度及索引 max_scores = similarity_matrix.max(axis=1) best_match_indices = similarity_matrix.argmax(axis=1) # 替换满足阈值的姓名,不满足则保留原名称 df['姓名'] = np.where( max_scores > 80, np.array(standard_names)[best_match_indices], df['姓名'] )
方案2:优化原逻辑的向量化操作(无需换库)
如果不想更换依赖库,可通过广播计算减少循环次数:
from fuzzywuzzy import fuzz import pandas as pd standard_names = ['Andrea Glz', 'Lineth Arce'] std_series = pd.Series(standard_names) def match_name(name): # 一次性计算当前姓名与所有标准名的相似度 ratios = std_series.apply(lambda x: fuzz.token_set_ratio(x, name)) best_idx = ratios.idxmax() return standard_names[best_idx] if ratios.iloc[best_idx] > 80 else name df['姓名'] = df['姓名'].apply(match_name)
方案3:自动生成标准名(基于首次出现的名称)
如果不需要预定义标准名,想直接把每组相似姓名统一为组内首次出现的名称(符合你给出的预期结果),可采用分组填充的方式:
from rapidfuzz import fuzz import pandas as pd # 计算当前行与上一行的相似度 df['similarity'] = df.apply(lambda row: fuzz.token_set_ratio(row['姓名'], df['姓名'].shift(1)), axis=1) # 按相似度分割分组:相似度≤80时视为新组起点 df['group'] = (df['similarity'] <= 80).cumsum() # 每组统一使用第一个出现的姓名 df['姓名'] = df.groupby('group')['姓名'].transform('first') # 清理临时列 df.drop(['similarity', 'group'], axis=1, inplace=True)
内容的提问来源于stack exchange,提问作者Init5 God
相关产品推荐
相关产品推荐

