带条件的DataFrame姓名模糊匹配需求实现
Pandas DataFrame 姓名模糊匹配实现方案
需求回顾
需要对两个DataFrame(df1、df2)完成姓名模糊匹配,满足以下要求:
- 匹配度阈值可灵活调整(默认高于40%)
- 排除同ID的姓名匹配对
- 若
df1某姓名与df2同一ID下多个姓名匹配,仅保留该ID组内匹配度最高的结果
依赖库安装
先安装模糊匹配所需工具:
pip install pandas fuzzywuzzy python-Levenshtein
python-Levenshtein用于提升匹配计算速度,大数据量场景建议必装。
完整实现代码
1. 导入库与示例数据
import pandas as pd from fuzzywuzzy import fuzz # 示例df1数据(唯一ID) df1 = pd.DataFrame({ 'ID': {0: 12445, 1: 23455, 2: 93854, 3: 98736}, 'Name': {0: 'John Smith', 1: 'Jack Smith', 2: 'David Brown', 3: 'Jason Smitdt'}, 'A': {0: 'a', 1: 'a', 2: 'x', 3: 'a'}, 'B': {0: 'b', 1: 'b', 2: 'y', 3: 'b'} }) # 示例df2数据(非唯一ID) df2 = pd.DataFrame({ 'ID': {0: 12445, 1: 12445, 2: 23455, 3: 93854, 4: 98736, 5: 98736}, 'Name': {0: 'John Smith', 1: 'Johny Smith', 2: 'Jack Smith', 3: 'David Brown', 4: 'Jason Smitdt', 5: 'Jesse Smith'}, 'A': {0: 'a', 1: 'a', 2: 'a', 3: 'x', 4: pd.NA, 5: pd.NA}, 'B': {0: 'b', 1: 'b', 2: 'b', 3: 'y', 4: pd.NA, 5: pd.NA} })
2. 核心匹配逻辑
# 1. 生成所有跨DataFrame的组合,排除同ID的匹配对 cross_merged = df1.assign(key=1).merge(df2.assign(key=1), on='key').drop('key', axis=1) cross_merged = cross_merged[cross_merged['ID_x'] != cross_merged['ID_y']] # 2. 计算每对姓名的模糊匹配度(基于Levenshtein距离) cross_merged['match_score'] = cross_merged.apply( lambda row: fuzz.ratio(row['Name_x'], row['Name_y']), axis=1 ) # 3. 按`df1.ID`和`df2.ID`分组,保留每组内匹配度最高的记录 # 若同一组存在多个相同最高分数,默认全部保留;需仅留一个可添加`.head(1)` top_matches = cross_merged.groupby(['ID_x', 'ID_y'], as_index=False).apply( lambda group: group[group['match_score'] == group['match_score'].max()] ).reset_index(drop=True) # 4. 应用匹配度阈值过滤结果(可灵活调整阈值) threshold = 40 final_result = top_matches[top_matches['match_score'] > threshold] # 重命名列以提升可读性 final_result = final_result.rename(columns={ 'ID_x': 'df1_ID', 'Name_x': 'df1_Name', 'A_x': 'df1_A', 'B_x': 'df1_B', 'ID_y': 'df2_ID', 'Name_y': 'df2_Name', 'A_y': 'df2_A', 'B_y': 'df2_B' }) # 查看最终结果 print(final_result)
关键逻辑说明
- 排除同ID匹配:通过
cross_merged[cross_merged['ID_x'] != cross_merged['ID_y']]过滤掉两个DataFrame ID相同的组合 - 灵活调整阈值:只需修改
threshold变量即可改变匹配度要求 - 保留最高匹配度:通过
groupby(['ID_x', 'ID_y'])分组后,筛选每组内match_score最大值对应的记录
示例输出(简化版)
| df1_ID | df1_Name | df1_A | df1_B | df2_ID | df2_Name | df2_A | df2_B | match_score |
|---|---|---|---|---|---|---|---|---|
| 12445 | John Smith | a | b | 23455 | Jack Smith | a | b | 82 |
| 12445 | John Smith | a | b | 98736 | Jesse Smith | w | 77 | |
| 23455 | Jack Smith | a | b | 12445 | John Smith | a | b | 82 |
| 23455 | Jack Smith | a | b | 98736 | Jesse Smith | w | 77 | |
| 93854 | David Brown | x | y | 12445 | John Smith | a | b | 45 |
| 98736 | Jason Smitdt | a | b | 12445 | John Smith | a | b | 55 |
内容的提问来源于stack exchange,提问作者nzskra
相关产品推荐
相关产品推荐

