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

如何用Fuzzywuzzy高效对比不等长字符串列表并生成多相似度指标

高效字符串相似度匹配优化方案

核心问题分析

原方案的效率瓶颈主要有两点:一是双重循环遍历所有组合(1.5亿次计算)带来的时间开销;二是循环内反复拼接DataFrame(pd.concat每次都会创建新对象,内存和时间成本极高);另外Fuzzywuzzy本身是纯Python实现,性能存在上限。

以下是针对性的优化方案:


1. 替换工具库:用RapidFuzz替代Fuzzywuzzy

RapidFuzz是Fuzzywuzzy的高性能替代,底层基于C++实现,API与Fuzzywuzzy完全兼容,但计算速度能提升几十到上百倍,是处理大规模字符串匹配的首选。

2. 避免逐行循环与低效拼接

先生成两个数据集的笛卡尔积,再批量计算相似度指标,最后过滤符合阈值的结果——彻底摆脱双重循环和逐次拼接的低效操作。

3. 可选预过滤:减少无效计算量

对字符串做预处理(转小写、去除特殊字符),或通过n-gram/Jaccard相似度快速过滤明显不相似的组合,进一步减少后续需要计算的样本量。


具体实现代码

步骤1:安装依赖

pip install rapidfuzz pandas

步骤2:基础高效实现

import pandas as pd
from rapidfuzz import fuzz

# 示例数据
forbes = pd.DataFrame(
    {
        "company_name": [
            "Deloitte",
            "PriceWaterhouseCoopers",
            "KPMG",
            "Ernst & Young",
            "intentionall typo company XYZ",
        ],
        "revenue": [100, 200, 300, 250, 400],
    }
)

sf = pd.DataFrame(
    {"salesforce_name": ["Deloite", "PriceWaterhouseCooper"], "CEO": ["John", "Jane"]}
)

# 生成笛卡尔积:一次性合并所有可能的组合(替代双重循环)
cross_df = pd.merge(forbes.assign(key=1), sf.assign(key=1), on="key").drop("key", axis=1)

# 批量计算相似度指标
cross_df["r"] = cross_df.apply(lambda x: fuzz.ratio(x["company_name"], x["salesforce_name"]), axis=1)
cross_df["pr"] = cross_df.apply(lambda x: fuzz.partial_ratio(x["company_name"], x["salesforce_name"]), axis=1)
cross_df["tsr"] = cross_df.apply(lambda x: fuzz.token_sort_ratio(x["company_name"], x["salesforce_name"]), axis=1)
cross_df["tser"] = cross_df.apply(lambda x: fuzz.token_set_ratio(x["company_name"], x["salesforce_name"]), axis=1)

# 过滤符合阈值的结果
filtered_scores = cross_df[(cross_df["r"] > 80) | (cross_df["pr"] > 80) | (cross_df["tsr"] > 80) | (cross_df["tser"] > 80)]

# 调整列名匹配需求
final_scores = filtered_scores.rename(columns={
    "company_name": "forbes_company",
    "salesforce_name": "salesforce_company"
})[["forbes_company", "salesforce_company", "r", "pr", "tsr", "tser"]]

print(final_scores)

进阶优化:使用矢量化API(更快)

RapidFuzz提供了矢量化计算接口,比apply效率更高,适合处理5万+3万的大规模数据:

from rapidfuzz import vectorized

# 提取字符串数组
forbes_names = cross_df["company_name"].values
sf_names = cross_df["salesforce_name"].values

# 矢量化批量计算所有指标
cross_df["r"] = vectorized.ratio(forbes_names, sf_names)
cross_df["pr"] = vectorized.partial_ratio(forbes_names, sf_names)
cross_df["tsr"] = vectorized.token_sort_ratio(forbes_names, sf_names)
cross_df["tser"] = vectorized.token_set_ratio(forbes_names, sf_names)

# 后续过滤步骤同上

预过滤示例(可选)

通过2-gram的Jaccard相似度先过滤掉明显不相似的组合,减少后续模糊计算的量:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import jaccard_score

def char_ngram_jaccard(s1, s2, n=2):
    vec = CountVectorizer(ngram_range=(n,n), analyzer='char').fit([s1, s2])
    vec1 = vec.transform([s1]).toarray()[0]
    vec2 = vec.transform([s2]).toarray()[0]
    return jaccard_score(vec1, vec2)

# 先过滤Jaccard相似度>0.5的组合
cross_df = cross_df[cross_df.apply(lambda x: char_ngram_jaccard(x["company_name"], x["salesforce_name"]) > 0.5, axis=1)]

# 再执行后续模糊相似度计算

性能对比

  • 原方案:双重循环+Fuzzywuzzy+逐次concat,1.5亿次计算预计耗时数小时
  • 优化方案:RapidFuzz矢量化+笛卡尔积批量计算,预计耗时几分钟(硬件不同略有差异,速度提升可达50-100倍)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:21:07