使用Fuzzywuzzy模糊匹配后合并DataFrame结果不符的问题排查
问题分析与解决方案
核心问题原因
1. 匹配算法与阈值设置不合理
你用的process.extract默认采用全字符串匹配(ratio),这种方式对长短差异大的字符串(比如Apple Souce和apple)得分极低:
Apple Souce与apple的ratio得分仅约54,远低于你设置的85阈值,直接被过滤Apple Souce与app的得分更低,自然无法匹配John tabel与Jon table的ratio得分约88,理论上能过85阈值,但可能因拼写细节(tabelvstable)导致得分刚好低于阈值,从而被过滤
2. 匹配方向与逻辑缺陷
当前逻辑是用df1的长字符串去匹配df2的短字符串,而你需要的是短字符串作为长字符串的子串/变体匹配,默认的全字符串匹配完全不适用这种场景。
修正后的代码实现
步骤1:优化模糊匹配函数
改用partial_ratio(子串匹配),同时降低阈值、统一字符串大小写以提升匹配准确率:
from fuzzywuzzy import fuzz, process import pandas as pd def fuzzy_merge(df_1, df_2, key1, key2, threshold=60): # 统一转为小写,消除大小写影响 df_1[key1] = df_1[key1].str.lower() df_2[key2] = df_2[key2].str.lower() s = df_2[key2].tolist() # 使用partial_ratio做子串匹配,适配长短字符串匹配场景 m = df_1[key1].apply(lambda x: process.extract(x, s, scorer=fuzz.partial_ratio)) 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 df_1 = df_1.assign(matches=df_1.matches.str.split(',')).explode('matches') # 清理空的匹配项 df_1['matches'] = df_1['matches'].str.strip().replace('', None) return df_1
步骤2:执行匹配与合并
df1 = pd.DataFrame({'Key':['Apple Souce', 'Banana', 'Orange', 'Strawberry', 'John tabel']}) df2 = pd.DataFrame({'Key2':['Aple suce','apple','app','orange', 'Mango', 'Orag','Jon table', 'Straw', 'Bannanna', 'Berry'],'Key23':['1', '2', '2','3', '3','4','4', '5', '6', '7']}) # 执行模糊匹配 df = fuzzy_merge(df1, df2, 'Key', 'Key2', threshold=60) # 执行outer join,保留所有未匹配项 merge = pd.merge(df, df2, left_on=['matches'], right_on=['Key2'], how='outer') # 填充空值为0,恢复原始字符串大小写 merge['Key'] = merge['Key'].fillna(0).replace(df1['Key'].str.lower().tolist(), df1['Key'].tolist()) merge['Key2'] = merge['Key2'].fillna(0) merge['Key23'] = merge['Key23'].fillna(0) print(merge)
步骤3:进阶匹配规则(可选)
如果需要更精准的拆分词匹配(比如Strawberry匹配Straw和Berry),可以改用token_set_ratio,它会拆分字符串为token后再匹配:
# 在fuzzy_merge函数中替换scorer参数 m = df_1[key1].apply(lambda x: process.extract(x, s, scorer=fuzz.token_set_ratio))
最终结果说明
修正后会得到符合预期的结果:
Apple Souce能匹配到Aple suce、apple、appStrawberry能匹配到Straw和Berry- 保留所有未匹配项(
John tabel和Jon table的未匹配情况),可通过微调阈值进一步适配
内容的提问来源于stack exchange,提问作者hyeri
相关产品推荐
相关产品推荐

