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

如何在不等长Pandas DataFrame列间计算多类字符串编辑距离?

为不等长Pandas DataFrame计算多类字符串编辑距离指标

需求说明

我有两个需通过公司名关联的Pandas DataFrame,其中一个包含约50000个唯一公司名,另一个约有5000个,两个数据集内均可能存在重复公司名。需要计算两DataFrame对应列的多类字符串编辑距离指标(如Jaro-Winkler、Levenshtein等),并生成包含这些指标的结果表。

示例数据集

import pandas as pd

mwe1 = pd.DataFrame(
    {
        'company_name': [
            'Deloitte', 
            'PriceWaterhouseCoopers', 
            'KPMG',
            'Ernst & Young',
            'intentionall typo company XYZ'
        ],
        'revenue': [100, 200, 300, 250, 400]
    }
)

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

期望输出

company_name                   revenue    salesforce_name         CEO     similarity_score ...
Deloitte                       100        Deloite                 John    98
PriceWaterhouseCoopers         200        Deloite                 John    0
KPMG                           300        Deloite                 John    15
Ernst & Young                  250        Deloite                 John    10
intentionall typo company XYZ  400        Deloite                 John    2
Deloitte                       100        PriceWaterhouseCooper   Jane    20
PriceWaterhouseCoopers         200        PriceWaterhouseCooper   Jane    97
KPMG                           300        PriceWaterhouseCooper   Jane    5
Ernst & Young                  250        PriceWaterhouseCooper   Jane    7
intentionall typo company XYZ  400        PriceWaterhouseCooper   Jane    3

现有基础

已掌握单个字符串的编辑距离计算方法,但不清楚如何应用到长度不等的Pandas Series:

import abydos.distance as abd
abd.DiscountedLevenshtein().sim('coca-cola company','coca-cola group')

解决方案

步骤1:生成两DataFrame的笛卡尔积

要让每个mwe1的公司名和mwe2的每个公司名都配对,需要先生成两个数据集的笛卡尔积,可通过临时列合并实现:

# 添加临时列用于合并
mwe1['dummy'] = 1
mwe2['dummy'] = 1

# 生成笛卡尔积并删除临时列
merged_df = pd.merge(mwe1, mwe2, on='dummy').drop('dummy', axis=1)

步骤2:封装多类相似度计算函数

基于abydos库封装函数,同时计算多种编辑距离相似度,并将结果转为百分比整数形式(匹配示例输出):

import abydos.distance as abd

def calculate_similarity(col1, col2):
    # Jaro-Winkler相似度(转百分比取整)
    jaro_winkler = round(abd.JaroWinkler().sim(col1, col2) * 100)
    # 折扣Levenshtein相似度(转百分比取整)
    discounted_lev = round(abd.DiscountedLevenshtein().sim(col1, col2) * 100)
    # 普通Levenshtein相似度(转百分比取整)
    levenshtein = round(abd.Levenshtein().sim(col1, col2) * 100)
    
    return pd.Series(
        [jaro_winkler, discounted_lev, levenshtein],
        index=['jaro_winkler_score', 'discounted_lev_score', 'levenshtein_score']
    )

步骤3:应用函数生成结果表

将函数应用到笛卡尔积DataFrame的公司名字段,合并原数据与相似度指标得到最终结果:

# 批量计算相似度
similarity_scores = merged_df.apply(
    lambda row: calculate_similarity(row['company_name'], row['salesforce_name']),
    axis=1
)

# 合并原数据与相似度指标
final_df = pd.concat([merged_df, similarity_scores], axis=1)

# 按需查看指定列结果
print(final_df[['company_name', 'revenue', 'salesforce_name', 'CEO', 'discounted_lev_score']])

性能优化提示

由于两个数据集规模较大(50000×5000=2.5亿行),直接计算笛卡尔积可能内存不足,可尝试以下优化:

  • 先对两个DataFrame去重,减少配对数量
  • 使用分块处理,逐批次计算相似度
  • 改用更高效的向量化计算库(如rapidfuzz)提升运算速度

内容的提问来源于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:16:12