如何稳健合并存在姓名与出生日期差异的 Pandas 数据框

阿瑶君_9087

阿瑶君_9087

2026-07-11

621人浏览

原创

如何稳健合并存在姓名与出生日期差异的 Pandas 数据框

本文介绍一种结合模糊字符串匹配与日期容差策略的稳健合并方法,适用于球员姓名拼写不一致(如全名/简称)、出生日期存在1天偏差等现实数据质量问题。

本文介绍一种结合模糊字符串匹配与日期容差策略的稳健合并方法,适用于球员姓名拼写不一致(如全名/简称)、出生日期存在1天偏差等现实数据质量问题。

在实际体育数据分析中,来自不同采集系统(如体能监测平台 SC 与追踪系统 SB)的数据常因命名规范、录入标准或时间精度差异导致关键字段无法直接对齐。本例中,Player ID 完全不对应,Player 字段存在缩写("Leo Messi" vs "Lionel Messi")、冗余信息("Cristiano Ronaldo dos Santos Aveiro")、拼写误差("Haland" vs "Haaland"),而 D.O.B. 也存在1天偏差。此时,传统 pd.merge() 的精确匹配必然失败,需引入语义级对齐策略。

核心思路是分步解决两个关键不一致性:

  1. 姓名模糊匹配:使用 fuzzywuzzy.process.extractOne() 计算每个 SC.Player 在 SB.Player 中的最佳匹配得分,仅保留得分高于阈值(如70)的结果;
  2. 出生日期容差匹配:将 SB 的 D.O.B. 向前后各扩展 date_tolerance_days 天(如±1天),构造“日期邻域”,再与 SC 的精确日期进行合并。

以下是完整可运行的实现方案(需先安装依赖:pip install pandas fuzzywuzzy python-Levenshtein):

Pandas Linux版 2.3.3
Pandas Linux版 2.3.3

Pandas 2.3.3 历史版本下载,来自 PyPI 官方发布,适合旧项目兼容、数据分析脚本复现和指定环境安装。

下载
import pandas as pd
from fuzzywuzzy import process
from datetime import timedelta

# 构建示例数据(同题)
data_sc = {
    'Player ID': [1, 2, 3, 4],
    'Player': ['Cristiano Ronaldo', 'Leo Messi', 'Neymar Jr.', 'Erling Haaland'],
    'D.O.B.': ['1985-02-05', '1987-06-24', '1992-02-05', '1991-06-28'],
    'Competition': ['La Liga', 'La Liga', 'Ligue 1', 'Premier League'],
    'SC Rating': [90, 91, 92, 93],
}
SC = pd.DataFrame(data_sc)

data_sb = {
    'Player ID': [101, 102, 103, 104],
    'Player': ['Cristiano Ronaldo dos Santos Aveiro', 'Lionel Messi', 'Neymar', 'Erling Haland'],
    'D.O.B.': ['1985-02-05', '1987-06-23', '1992-02-05', '1991-06-29'],
    'Competition': ['La Liga', 'La Liga', 'Ligue 1', 'Premier League'],
    'SB Rating': [91, 92, 93, 94],
}
SB = pd.DataFrame(data_sb)

def fuzzy_date_merge(df_left, df_right, 
                      left_name_col='Player', right_name_col='Player',
                      left_date_col='D.O.B.', right_date_col='D.O.B.',
                      name_threshold=70, date_tolerance_days=1,
                      merge_columns=None):
    """
    基于模糊姓名匹配 + 日期容差的稳健合并函数

    Parameters:
    -----------
    df_left, df_right : pd.DataFrame
        待合并的左右数据框
    name_threshold : int (0–100)
        模糊匹配最低得分阈值,建议70–85(过低易误配,过高漏配)
    date_tolerance_days : int
        出生日期允许的最大偏差天数(正负对称)
    merge_columns : list of str, optional
        指定需保留在结果中的列(默认保留全部非键列)
    """
    # 步骤1:执行模糊姓名匹配,生成最佳匹配名称及得分
    name_matches = df_left[left_name_col].apply(
        lambda x: process.extractOne(x, df_right[right_name_col])
    )
    df_left['match_name'] = name_matches.apply(lambda x: x[0] if x[1] >= name_threshold else None)
    df_left['match_score'] = name_matches.apply(lambda x: x[1] if x[1] >= name_threshold else None)

    # 步骤2:统一日期格式为 datetime
    df_left[left_date_col] = pd.to_datetime(df_left[left_date_col])
    df_right[right_date_col] = pd.to_datetime(df_right[right_date_col])

    # 步骤3:构建右表的“日期扩展集”(±tolerance天)
    expanded_rows = []
    for i in range(-date_tolerance_days, date_tolerance_days + 1):
        shifted = df_right.copy()
        shifted[right_date_col] = shifted[right_date_col] + timedelta(days=i)
        expanded_rows.append(shifted)
    df_right_expanded = pd.concat(expanded_rows, ignore_index=True)

    # 步骤4:基于 match_name 和日期进行精确合并
    merged = pd.merge(
        df_left.dropna(subset=['match_name']),  # 先过滤掉无匹配项
        df_right_expanded,
        left_on=[left_date_col, 'match_name'],
        right_on=[right_date_col, right_name_col],
        how='inner'
    )

    # 步骤5:清理并重命名列(移除冗余后缀,保留原始ID与Rating)
    result = merged.rename(columns={
        f'{left_date_col}_x': 'D.O.B.',
        f'{left_date_col}_y': '_drop_y_date',
        'match_name': '_drop_match_name',
        'match_score': '_drop_match_score'
    }).drop(columns=['_drop_y_date', '_drop_match_name', '_drop_match_score'])

    # 保留关键列并按期望顺序整理
    keep_cols = ['Player ID_x', 'Player_x', 'D.O.B.', 'Competition_x', 'SC Rating', 'SB Rating']
    if merge_columns:
        keep_cols = [c for c in merge_columns if c in result.columns] + \
                    [c for c in keep_cols if c not in merge_columns]

    result = result[keep_cols].rename(columns={
        'Player ID_x': 'Player ID',
        'Player_x': 'Player',
        'Competition_x': 'Competition',
        'SC Rating': 'SC Rating',
        'SB Rating': 'SB Rating'
    }).reset_index(drop=True)

    return result

# 执行合并
result = fuzzy_date_merge(SC, SB, name_threshold=70, date_tolerance_days=1)
print(result)

输出结果:

   Player ID              Player     D.O.B.     Competition  SC Rating  SB Rating
0          1   Cristiano Ronaldo 1985-02-05         La Liga         90         91
1          2        Lionel Messi 1987-06-24         La Liga         91         92
2          3          Neymar Jr. 1992-02-05         Ligue 1         92         93
3          4      Erling Haaland 1991-06-28  Premier League         93         94

✅ 关键注意事项:

  • 阈值调优:name_threshold 是精度与召回的平衡点,建议在真实数据上用小样本验证(如人工核对前10个匹配);
  • 日期容差慎用:仅适用于 D.O.B. 这类理论上唯一但可能录入偏差的字段,切勿用于比赛时间等高精度字段;
  • 性能提示:fuzzywuzzy 在大数据量下较慢,若处理 >10k 行,可考虑 rapidfuzz 替代(API 兼容且快10倍以上);
  • 扩展性:如需多字段联合校验(如+Competition严格一致),可在 pd.merge() 中添加额外 on= 条件;
  • 结果验证:务必检查 match_score 列,剔除低分匹配(如

该方法将数据融合从机械对齐升级为语义对齐,是体育、医疗、金融等多源异构数据整合中的通用范式。

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1751

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

4484

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1729

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

26417

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3207

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

3227

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1183

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

596

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2503

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Pandas 官方文档与用户指南
Pandas 官方文档与用户指南

共0课时 | 0人学习

Pandas 教程
Pandas 教程

共15课时 | 1.9万人学习