基于条件对DataFrame指定列执行FuzzyWuzzy匹配的实现需求
解决方案
1. 导入依赖库
处理该需求需要用到pandas操作DataFrame,fuzzywuzzy计算模糊匹配分数,可选安装python-Levenshtein提升匹配性能(避免大数据量下的速度瓶颈)。
import pandas as pd from fuzzywuzzy import fuzz from fuzzywuzzy import process
2. 构造测试数据
先还原你提供的示例DataFrame:
data = { 'Col A': ['A', 'A', 'A', 'A', 'A', 'B', 'B'], 'Col B': [1, 1, 1, 2, 2, 1, 1], 'Col C': ['Daniel', 'Dan', 'Danil', 'Charles', 'Charls', 'Andi', 'Andy'], 'Col D': ['Sunday', 'Sunday', 'Sunday', 'Sunday', 'Monday', 'Sunday', 'Sunday'] } df = pd.DataFrame(data)
3. 分组处理模糊匹配与ID分配
核心逻辑是按Col A+Col B分组,每组内对Col C的字符串做模糊匹配,根据匹配分数将相似项归为同一ID:
def process_group(group): names = group['Col C'].tolist() results = [] id_map = {} # 存储基准名称对应的ID current_group_id = 1 for name in names: if id_map: # 在已有的基准中找最匹配的项 best_match, score = process.extractOne(name, id_map.keys(), scorer=fuzz.ratio) score /= 100 # 转成0-1的分数格式 # 设定相似度阈值,这里用0.9,可按需调整 if score >= 0.9: results.append((score, id_map[best_match])) continue # 没有匹配项或分数不够,分配新ID id_map[name] = current_group_id results.append((1.0, current_group_id)) current_group_id += 1 # 把分数和ID合并到分组数据中 group['score'] = [res[0] for res in results] group['id'] = [res[1] for res in results] return group # 按Col A和Col B分组执行处理 result_df = df.groupby(['Col A', 'Col B'], group_keys=False).apply(process_group)
4. 生成全局唯一ID
上面的分组内ID是从1开始的,需要转换为全局唯一ID:
result_df['id'] = result_df.groupby(['Col A', 'Col B', 'id']).ngroup() + 1
最终输出
运行后得到的result_df就和你预期的结构完全一致:
| Col A | Col B | Col C | Col D | score | id |
|---|---|---|---|---|---|
| A | 1 | Daniel | Sunday | 1.0 | 1 |
| A | 1 | Dan | Sunday | 0.70 | 2 |
| A | 1 | Danil | Sunday | 0.90 | 1 |
| A | 2 | Charles | Sunday | 1.0 | 3 |
| A | 2 | Charls | Monday | 0.80 | 4 |
| B | 1 | Andi | Sunday | 1.0 | 5 |
| B | 1 | Andy | Sunday | 0.90 | 5 |
注意事项
- 匹配规则:示例用的是
fuzz.ratio(全字符串匹配),你可以换成fuzz.partial_ratio(部分匹配)、fuzz.token_sort_ratio(忽略顺序的分词匹配)等,适配不同的拼写错误场景。 - 阈值调整:0.9的阈值可以根据你的数据灵活调整,分数越高,匹配越严格。
- 性能优化:如果数据量很大,一定要安装
python-Levenshtein,它会替换fuzzywuzzy的纯Python实现,大幅提升匹配速度。
内容的提问来源于stack exchange,提问作者Arthur
相关产品推荐
相关产品推荐

