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

如何合并存在数据不一致问题的Pandas DataFrame?

问题:合并存在字段格式差异的两个Pandas DataFrame

我有两个Pandas DataFrame:SC和SB:

  • SC包含赛事中足球运动员的体能统计数据
  • SB包含赛事中足球运动员的追踪统计数据

示例数据

import pandas as pd

# Sample data for SC (physical statistics)
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)

# Sample data for SB (tracking statistics)
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)

期望输出

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

两个DataFrame的共同字段包括:Player ID、Player、D.O.B.、Competition。但来自不同数据源,变量格式和规范存在差异:

  • 同一球员在两个数据集的Player ID值不同
  • Player字段中球员姓名的写法/拼写不一致(比如Messi的简称/全名、Haaland的拼写差异)
  • D.O.B.字段中同一球员的出生日期可能存在误差(比如Messi差1天、Haaland差1天)

请问该如何完成此次合并?


解决方案

步骤1:标准化姓名字段

先对两个DataFrame的Player字段做标准化处理,提取核心姓名,减少拼写/格式差异的影响:

import re

def standardize_name(name):
    # 转换为小写,去除多余空格
    name_clean = re.sub(r'\s+', ' ', name.strip().lower())
    # 针对示例球员的专属匹配规则,可根据实际数据扩展
    if 'ronaldo' in name_clean:
        return 'cristiano ronaldo'
    elif 'messi' in name_clean:
        return 'lionel messi'
    elif 'neymar' in name_clean:
        return 'neymar jr.'
    elif 'haaland' in name_clean or 'haland' in name_clean:
        return 'erling haaland'
    # 通用规则:取姓名前两个核心词(可按需调整)
    return ' '.join(name_clean.split()[:2])

SC['Standardized Player'] = SC['Player'].apply(standardize_name)
SB['Standardized Player'] = SB['Player'].apply(standardize_name)

步骤2:筛选匹配对(处理日期误差)

将D.O.B.转为日期类型,通过多条件筛选找到同一球员的匹配记录:

# 转换日期格式
SC['D.O.B.'] = pd.to_datetime(SC['D.O.B.'])
SB['D.O.B.'] = pd.to_datetime(SB['D.O.B.'])

# 生成交叉表,筛选符合条件的匹配项
cross_merge = SC.merge(SB, how='cross', suffixes=('_sc', '_sb'))
valid_matches = cross_merge[
    # 标准化姓名一致
    (cross_merge['Standardized Player_sc'] == cross_merge['Standardized Player_sb']) &
    # 赛事一致
    (cross_merge['Competition_sc'] == cross_merge['Competition_sb']) &
    # 出生日期误差≤1天
    (abs(cross_merge['D.O.B._sc'] - cross_merge['D.O.B._sb']).dt.days <= 1)
]

步骤3:整理最终结果

从匹配结果中提取所需字段,保留SC的原始标识并合并SB的评分:

final_result = valid_matches[[
    'Player ID_sc', 'Player_sc', 'D.O.B._sc', 'Competition_sc',
    'SC Rating', 'SB Rating'
]].rename(columns={
    'Player ID_sc': 'Player ID',
    'Player_sc': 'Player',
    'D.O.B._sc': 'D.O.B.',
    'Competition_sc': 'Competition'
}).reset_index(drop=True)

print(final_result)

运行后即可得到符合期望的输出。

补充优化建议

  • 若数据量较大,可先按Competition分组后再做交叉合并,减少计算量
  • 姓名标准化规则可根据实际数据扩展(比如处理更多球员的别名、拼写变体)
  • 日期误差阈值可根据数据源的精度调整(比如允许2天以内的误差)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 11:46:06