用Python的RapidFuzz库5分钟解决Excel人名匹配难题工作中经常遇到这样的场景从CRM系统导出的客户名单里写着张总而市场部提供的表格中却记录为张三丰。手工核对不仅耗时费力还容易遗漏重要客户。今天我们就用Python的RapidFuzz库教你5分钟搞定这类模糊人名匹配问题。1. 环境准备与数据加载首先确保安装了必要的库。打开命令行执行以下命令pip install pandas openpyxl rapidfuzz这里我们选择openpyxl作为Excel引擎因为它对.xlsx格式支持更好。假设我们有两个Excel文件客户名单.xlsx包含系统导出的客户信息市场活动名单.xlsx包含市场部收集的参与活动人员用pandas加载数据import pandas as pd # 读取Excel文件 df_customers pd.read_excel(客户名单.xlsx) df_marketing pd.read_excel(市场活动名单.xlsx) # 查看前几行 print(df_customers.head()) print(df_marketing.head())典型的数据结构可能如下客户ID客户姓名联系电话1001张总138****12341002李经理139****5678活动ID参与者参与时间A001张三丰2023-05-01A002李四2023-05-022. RapidFuzz核心匹配方法详解RapidFuzz提供了多种匹配算法针对人名匹配场景我们重点介绍三种最实用的方法2.1 token_set_ratio处理姓名顺序不一致当张三 李四和李四 张三这种顺序不一致时特别有效from rapidfuzz import fuzz # 示例比较 score fuzz.token_set_ratio(张三 李四, 李四 张三) print(score) # 输出100表示完全匹配2.2 partial_ratio处理姓名缩写或部分匹配适合张总匹配张三丰这类情况score fuzz.partial_ratio(张总, 张三丰) print(score) # 输出约83表示高度相似2.3 WRatio综合加权算法结合多种算法的优点适合大多数场景score fuzz.WRatio(John Smith, J. Smith) print(score) # 输出约903. 批量匹配实战操作现在我们用process.extract方法批量匹配两个表格中的人名from rapidfuzz import process # 提取姓名列转为列表 customers df_customers[客户姓名].tolist() marketing df_marketing[参与者].tolist() # 定义匹配函数 def fuzzy_match(name, choices): result process.extractOne( name, choices, scorerfuzz.WRatio, # 使用WRatio算法 score_cutoff80 # 只返回相似度80以上的结果 ) return result if result else (None, 0, None) # 为市场名单添加匹配结果 df_marketing[匹配客户] df_marketing[参与者].apply( lambda x: fuzzy_match(x, customers)[0] ) df_marketing[匹配分数] df_marketing[参与者].apply( lambda x: fuzzy_match(x, customers)[1] ) # 查看匹配结果 print(df_marketing[df_marketing[匹配分数] 0])输出结果示例活动ID参与者匹配客户匹配分数A001张三丰张总85A002李四李经理824. 结果优化与高级技巧4.1 预处理提高匹配精度在匹配前对数据进行清洗def preprocess_name(name): # 去除空格和特殊字符 name str(name).strip().replace( , ) # 统一转换为小写英文名适用 return name.lower() # 应用预处理 df_customers[清洗姓名] df_customers[客户姓名].apply(preprocess_name) df_marketing[清洗姓名] df_marketing[参与者].apply(preprocess_name)4.2 多列组合匹配当单一人名匹配不准时可以结合其他信息# 创建组合键 df_customers[组合键] df_customers[客户姓名] df_customers[联系电话].astype(str).str[-4:] df_marketing[组合键] df_marketing[参与者] df_marketing[参与时间].astype(str) # 使用组合键进行匹配4.3 保存匹配结果将最终结果导出到新Excel文件# 合并两个数据框 final_result pd.merge( df_marketing, df_customers, left_on匹配客户, right_on客户姓名, howleft ) # 保存到新文件 final_result.to_excel(匹配结果.xlsx, indexFalse)5. 常见问题解决方案5.1 匹配速度慢怎么办RapidFuzz本身已经很快但如果数据量特别大10万条可以考虑先对数据进行分组如按姓氏首字母使用process.extract的limit参数限制返回结果数量考虑使用多线程处理from concurrent.futures import ThreadPoolExecutor def batch_match(names): with ThreadPoolExecutor() as executor: results list(executor.map( lambda x: process.extractOne(x, customers, scorerfuzz.WRatio), names )) return results5.2 如何选择合适的相似度阈值根据实际测试建议场景推荐阈值严格匹配法律文件≥95一般业务匹配80-90宽松匹配初步筛选60-795.3 中文姓名特殊处理中文姓名匹配可以考虑使用拼音转换库如pypinyin提取姓氏单独匹配处理常见称谓总/经理/老师等from pypinyin import lazy_pinyin def name_to_pinyin(name): return .join(lazy_pinyin(name)) df_customers[拼音] df_customers[客户姓名].apply(name_to_pinyin)实际项目中我发现对包含称谓的姓名如张总先去除称谓再匹配效果更好。可以创建一个称谓字典进行过滤titles [总, 经理, 老师, 博士] def remove_title(name): for title in titles: name name.replace(title, ) return name