如何合并存在数据不一致问题的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
相关产品推荐
相关产品推荐

