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

Pandas中基于字符串相似度匹配列时NaN值未正确生成的问题排查

解决模糊匹配未生成预期NaN及错误保留低匹配结果的问题

问题根源

你的代码现在有两个核心问题导致结果不符合预期:

  1. 缺少匹配度阈值判断
    你当前的逻辑只是在dico2['Surname']里找出和当前Name匹配度最高的项——不管这个匹配度有多低。比如Zadig和Patrice4的匹配度虽然极低,但在给定的四个Surname里它是最高的,所以代码就把它作为Zadig的Surname返回了,完全没考虑"这个匹配是否足够靠谱"。

  2. 错误的NaN处理逻辑
    你的代码里从来没有生成过真正的NaN值(你只是最后试图删除等于字符串"NaN"的行),但map_list里只会出现dico2里的Surname值,所以那行删除代码根本不起作用。

看这段关键的循环代码就清楚了:

map_list = []
for name in dico['Name']:
    best_ratio = None
    for idx, surname in enumerate(dico2['Surname']):
        if best_ratio == None:
            best_ratio = fuzz.ratio(name, surname)
            best_idx = 0
        else:
            ratio = fuzz.ratio(name, surname)
            if ratio > best_ratio:
                best_ratio = ratio
                best_idx = idx
    map_list.append(dico2['Surname'][best_idx]) # 不管匹配度高低,硬塞一个值

这里没有任何逻辑判断"这个最佳匹配是否合格",所以哪怕匹配度只有10,也会把对应的Surname加进去。

修复方案

我们需要添加匹配度阈值,并且正确处理空值,下面是完整的修正代码:

import pandas as pd
from fuzzywuzzy import fuzz
import numpy as np

# 原始数据
dico = {'Name': ['Arthur','Henri','Lisiane','Patrice','Zadig','Sacha'], 
        "Age": ["20","18","62","73",'21','20'], 
        "Studies": ['Economics','Maths','Psychology','Medical','Cinema','CS'] }
dico2 = {'Surname': ['Arthur1','Henri2','Lisiane3','Patrice4']}

# 转成DataFrame(建议直接用DataFrame操作,比字典更方便)
df = pd.DataFrame(dico)
surname_df = pd.DataFrame(dico2)

map_list = []
# 设定匹配度阈值,这里用80,你可以根据实际情况调整(比如名字和姓氏前缀匹配度高的话可以设高一点)
MATCH_THRESHOLD = 80

for name in df['Name']:
    best_ratio = -1
    best_surname = np.nan  # 默认空值
    for surname in surname_df['Surname']:
        current_ratio = fuzz.ratio(name, surname)
        if current_ratio > best_ratio:
            best_ratio = current_ratio
            # 只有当匹配度超过阈值时,才更新为对应的姓氏
            if best_ratio >= MATCH_THRESHOLD:
                best_surname = surname
            else:
                # 匹配度不够,保持空值
                best_surname = np.nan
    map_list.append(best_surname)

# 添加Surname列到原DataFrame
df['Surname'] = map_list
# 调整列顺序
df = df[["Name", "Surname", "Age", "Studies"]]
# 删除Surname为空的行
df = df.dropna(subset=['Surname'])

print(df)

关键改进点

  • 阈值判断:新增了MATCH_THRESHOLD,只有当模糊匹配度超过这个值时,才会把对应的Surname赋值给Name,否则保留np.nan(pandas能识别的空值)。
  • 正确处理空值:用dropna(subset=['Surname'])直接删除空值行,这是pandas处理空值的标准方式,比判断字符串"NaN"靠谱得多。
  • 代码优化:把字典直接转成DataFrame操作,逻辑更清晰,也符合pandas的使用习惯。

运行结果

执行后会得到你预期的输出:

Name   Surname Age    Studies
0    Arthur  Arthur1  20  Economics
1     Henri   Henri2  18      Maths
2  Lisiane  Lisiane3  62 Psychology

内容的提问来源于stack exchange,提问作者Arthur Langlois

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 12:32:48