如何基于多列值用查找函数在Pandas DataFrame中新增列
解决方法:匹配对手的累计平均值列
我是Python新手,用Google Colab处理20支英超球队单赛季比赛的CSV数据。先计算各队的累计平均值,再合并成一个大DataFrame。当前DataFrame包含Date、Team、Opposition、cum_avg_xG等列(cum_avg_xG是球队截至对应日期的预期进球平均xG值),但存在比赛重复记录(比如曼城vs伯恩茅斯和伯恩茅斯vs曼城是同一场比赛)。现在需要新增opposition_cum_avg_xG列,根据Date和Opposition匹配对手的cum_avg_xG值(比如曼城对阵伯恩茅斯的行中,该列取伯恩茅斯的0.85),后续还要对cum_avg_GF等其他累计列做相同操作,不知道怎么基于多列在同一个DataFrame里实现这类查找。
核心逻辑
要实现这个需求,本质是把原数据里的球队累计值转换成一个可查询的"对手数据字典",然后通过日期+对手球队的组合,把对应的值匹配回去。
具体步骤
- 提取对手映射表:从合并后的大DataFrame里,把
Date、Team和所有累计列单独拎出来,把Team改名为Opposition——这样这张表就代表了"某日期下,某球队的累计值",正好对应原数据里"某日期下,对阵该球队的对手累计值"。 - 清理重复记录:因为同一场比赛会被两支球队各记录一次,所以映射表里可能存在重复的(Date, Opposition)组合,需要先去重,确保每个组合只有一条有效数据。
- 合并匹配数据:用
pd.merge把映射表和原数据关联起来,匹配键就是Date和Opposition,自动把对手的累计值填充到新列里。
修改后的完整代码
# 上传文件到Colab环境 from google.colab import files upload = files.upload() # 导入所需库 import pandas as pd import numpy as np import glob import os # 定义计算累计平均值的函数 def myfunction(team): df_team = pd.read_csv(team) # 计算各指标的累计平均值 df_team['cum_avg_xG'] = df_team['xG'].expanding().mean() df_team['cum_avg_GF'] = df_team['GF'].expanding().mean() df_team['cum_avg_GA'] = df_team['GA'].expanding().mean() df_team['cum_avg_shots'] = df_team['Sh'].expanding().mean() # 累计值下移一行(确保是该场比赛前的累计数据) df_team[['cum_avg_xG', 'cum_avg_GF', 'cum_avg_GA', 'cum_avg_shots']] = df_team[ ['cum_avg_xG','cum_avg_GF', 'cum_avg_GA', 'cum_avg_shots'] ].shift(1) df_team = df_team.reset_index(drop=True) return df_team # 合并所有球队的CSV数据 path = '/content/' all_files = glob.glob(os.path.join(path , "*.csv")) team_temp = [] for filename in all_files: df = myfunction(filename) team_temp.append(df) df_allteam = pd.concat(team_temp, axis=0, ignore_index=True) # ------------------------------ # 新增:匹配对手的累计平均值列 # ------------------------------ # 1. 创建对手数据映射表,重命名Team为Opposition cum_columns = ['cum_avg_xG', 'cum_avg_GF', 'cum_avg_GA', 'cum_avg_shots'] opponent_map = df_allteam[['Date', 'Team'] + cum_columns].rename( columns={'Team': 'Opposition'} ) # 清理重复记录:确保每个(Date, Opposition)组合只有一条数据(保留最后一条) opponent_map = opponent_map.drop_duplicates(subset=['Date', 'Opposition'], keep='last') # 2. 将对手数据合并到原DataFrame df_allteam = pd.merge( df_allteam, opponent_map, on=['Date', 'Opposition'], how='left', suffixes=('', '_opponent') ) # 3. 重命名对手列,统一前缀为opposition_ for col in cum_columns: df_allteam.rename(columns={f'{col}_opponent': f'opposition_{col}'}, inplace=True) # 查看处理后的结果 df_allteam.head()
关键细节说明
- 去重操作:
drop_duplicates(subset=['Date', 'Opposition'], keep='last')是为了避免合并后出现重复行,如果你的原始数据里每个(Date, Team)都是唯一的,这一步可以跳过,但加上更稳妥。 - 左连接方式:
how='left'保证原DataFrame的所有行都保留,要是遇到赛季第一场比赛(对手还没有累计数据),对应列会显示NaN,可以根据需求用df_allteam.fillna(0, inplace=True)填充。 - 列名重命名:通过后缀区分原列和对手列,再统一改成
opposition_cum_avg_xG这种格式,方便后续识别和使用。
内容的提问来源于stack exchange,提问作者Andreas Wong
相关产品推荐
相关产品推荐

