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

如何对两个pandas DataFrame应用fuzzy ratio实现模糊字符串匹配

原代码问题说明

你现有代码存在两个明显问题:

  1. 自定义函数get_ratio里两次取值都用了row['address'],且变量名和外部的sample1、sample2重名,无法正确取到两个DataFrame的地址字段
  2. 没有将两个sample的待比对字段合并成同一行可访问的结构,apply无法同时遍历两个独立的DataFrame

场景1:按索引位置一一对应比对两个样本的同序行

如果你的两个sample行数相同,要对比第1行和第1行、第2行和第2行的地址相似度,用这个方案:

import pandas as pd
from fuzzywuzzy import fuzz

# 你的采样逻辑保留
sample1 = pd.DataFrame(data1.sample(n=200, random_state=42))
sample2 = pd.DataFrame(data2.sample(n=200, random_state=13))

# 构造比对用的合并表,保留两个样本的地址字段
compare_df = pd.DataFrame({
    'addr_sample1': sample1['address'],
    'addr_sample2': sample2['address']
})

# 重写相似度计算函数
def get_ratio(row):
    return fuzz.token_set_ratio(row['addr_sample1'], row['addr_sample2'])

# 计算相似度并筛选结果
compare_df['match_score'] = compare_df.apply(get_ratio, axis=1)
match = compare_df[compare_df['match_score'] >= 78]
no_matched = compare_df[compare_df['match_score'] <= 77]

场景2:两个样本所有行两两交叉比对(找所有符合阈值的地址组合)

如果要遍历sample1的每一行,和sample2的所有行逐一比对相似度,用笛卡尔积合并的方案:

import pandas as pd
from fuzzywuzzy import fuzz

sample1 = pd.DataFrame(data1.sample(n=200, random_state=42))
sample2 = pd.DataFrame(data2.sample(n=200, random_state=13))

# 加临时键构造笛卡尔积,得到所有行的两两组合
sample1['tmp_join_key'] = 0
sample2['tmp_join_key'] = 0
cross_compare_df = sample1.merge(
    sample2, 
    on='tmp_join_key', 
    suffixes=('_s1', '_s2') # 重名字段自动加后缀区分
).drop('tmp_join_key', axis=1)

# 相似度计算函数
def get_ratio(row):
    return fuzz.token_set_ratio(row['address_s1'], row['address_s2'])

# 计算得分并筛选
cross_compare_df['match_score'] = cross_compare_df.apply(get_ratio, axis=1)
match = cross_compare_df[cross_compare_df['match_score'] >= 78]
no_matched = cross_compare_df[cross_compare_df['match_score'] <= 77]

性能优化建议

如果后续数据量变大,两两比对性能较差,可以用fuzzywuzzy的批量匹配接口优化,避免全量笛卡尔积计算:

from fuzzywuzzy import process

sample2_addr_list = sample2['address'].tolist()
# 对sample1的每个地址,直接找sample2中相似度最高的匹配
def match_top1(addr):
    top_match = process.extractOne(addr, sample2_addr_list, scorer=fuzz.token_set_ratio)
    return pd.Series([top_match[0], top_match[1]]) if top_match else pd.Series([None, 0])

sample1[['matched_addr_sample2', 'match_score']] = sample1['address'].apply(match_top1)
match = sample1[sample1['match_score'] >=78]
no_matched = sample1[sample1['match_score'] <=77]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:36:03