You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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阈值,但可能因拼写细节(tabel vs table)导致得分刚好低于阈值,从而被过滤

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、app
  • Strawberry能匹配到Straw和Berry
  • 保留所有未匹配项(John tabel和Jon table的未匹配情况),可通过微调阈值进一步适配

内容的提问来源于stack exchange,提问作者hyeri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 11:05:06