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

基于字符串部分匹配合并DataFrame的问题求助

解决方案:Pandas 模糊匹配合并(高效且准确)

问题背景

需要基于Name列合并两个DataFrame,但因名称存在特殊字符(如.、')、后缀差异(如Jr/Jr.、III缺失)、昵称/全名差异(如Nic/Nicolas)导致直接合并失败。试过fuzzywuzzy的process.extractOne速度过慢,difflib匹配结果不准确,需要高效且精准的合并方案。

数据示例

df1

NamePerformance
Matt Cole Jr89
Steve Smith72
DJ Watson91
Amar'e George92
Steve Nurkić84
Charles Long87
Nic Kitch73

df2

NameYear
Matt Cole Jr.2023
Steve Smith III2022
D.J. Watson2021
Amare George2020
Steve Nurkic2021
Charles Long Jr.2022
Nicolas Kitch2023

期望合并结果

NameYearPerformance
Matt Cole Jr.202389
Steve Smith III202272
D.J. Watson202191
Amare George202092
Steve Nurkic202184
Charles Long Jr.202287
Nicolas Kitch202373

尝试过的方法

  1. fuzzywuzzy(速度过慢)
from fuzzywuzzy import process

dfm = pd.DataFrame(df2["Name"].apply(lambda x: process.extractOne(x, df1["Name"])) .tolist()])
  1. difflib(匹配错误)
import difflib
from functools import partial

def get_closest_match(x,y):
    """x=possibilities , y = input"""
    f = partial(
    difflib.get_close_matches, possibilities=x.unique(), n=1,cutoff=0.5)

    matches = y.astype(str).drop_duplicates().map(f).fillna('').str[0]
    return pd.DataFrame([y,matches.rename('Name')]).T

temp = get_closest_match(df2['Name'],df1['Name'])
display(temp)

可行解决方案

方案1:先标准化名称,再用快速模糊匹配(推荐)

先对两个DataFrame的Name列做标准化处理,消除格式差异,再用rapidfuzz(比fuzzywuzzy快数十倍)做模糊匹配,最后合并。

步骤1:安装依赖

pip install rapidfuzz pandas

步骤2:定义名称标准化函数

import pandas as pd
from rapidfuzz import process, fuzz

def standardize_name(name):
    # 去除特殊字符(撇号、点号)
    name = name.replace("'", "").replace(".", "")
    # 移除重音符号并转小写(比如ć转c)
    name = name.normalize('NFKD').encode('ascii', errors='ignore').decode('utf-8').lower()
    return name

步骤3:添加标准化名称列

df1['standard_name'] = df1['Name'].apply(standardize_name)
df2['standard_name'] = df2['Name'].apply(standardize_name)

步骤4:匹配并合并

# 为df2的每个标准化名称匹配df1中最相似的结果
df2['matched_standard_name'] = df2['standard_name'].apply(
    lambda x: process.extractOne(x, df1['standard_name'], scorer=fuzz.WRatio)[0]
)

# 合并数据并整理列
merged_df = df2.merge(df1, left_on='matched_standard_name', right_on='standard_name', how='left')
merged_df = merged_df[['Name_x', 'Year', 'Performance']].rename(columns={'Name_x': 'Name'})

# 输出结果
print(merged_df)

方案2:直接使用rapidfuzz批量匹配(无需标准化)

如果不想做标准化,直接用rapidfuzz的批量匹配功能,效率远高于fuzzywuzzy:

from rapidfuzz import process, fuzz

# 批量匹配df2的Name到df1的Name
matches = process.extract(df2['Name'].tolist(), df1['Name'].tolist(), scorer=fuzz.WRatio, limit=1)

# 提取匹配结果并映射Performance列
df2['matched_name'] = [match[0] for match in matches]
df2['Performance'] = df2['matched_name'].map(df1.set_index('Name')['Performance'])

# 整理结果列
merged_df = df2[['Name', 'Year', 'Performance']]
print(merged_df)

方案说明

  • 标准化的作用:消除格式差异(如.、'、重音),让模糊匹配更精准,同时减少计算量。
  • rapidfuzz优势:C语言实现的模糊匹配算法,速度比fuzzywuzzy快数倍,适合处理较大数据集。
  • WRatio评分器:能较好处理大小写、空格、后缀差异,比默认评分器更适合人名匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 23:07:44