如何在不等长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
相关产品推荐
相关产品推荐

