Pandas按主客队两列过滤DataFrame计算控球率平均值实现问题
问题需求
我有如下DataFrame:
Unnamed: 0 Datetime HomeTeam AwayTeam Ball PossessionMatch_H Ball PossessionMatch_A 0 0 2021-05-24 02:30:00 U. De Chile Everton 68 32 1 1 2021-05-23 21:00:00 Huachipato Colo Colo 48 52 2 2 2021-05-23 18:30:00 Melipilla Antofagasta 47 53 3 3 2021-05-23 02:30:00 U. Espanola U. Catolica 37 63 4 4 2021-05-23 00:00:00 S. Wanderers O'Higgins 29 71 ... ... ... ... ... ... ... 57 57 2021-03-28 15:45:00 Palestino Antofagasta 58 42 58 58 2021-03-28 01:00:00 U. Espanola S. Wanderers 50 50 59 59 2021-03-27 22:30:00 Colo Colo Union La Calera 58 42 60 60 2021-03-27 20:00:00 Everton O'Higgins 54 46 61 61 2021-03-27 15:00:00 Curico Unido Melipilla 41 59
需要实现如下需求:
- 按行计算主队、客队在本场比赛之前所有赛事的平均控球率
- 新增
Ball PossessionMatch_H/MP列存储本场主队的历史平均控球率 - 新增
Ball PossessionMatch_A/MP列存储本场客队的历史平均控球率 - 结果直接追加到原DataFrame中,不要出现重复行
原代码问题排查
- 分支判断逻辑错误:
team in df['HomeTeam']是判断team是否在Series的索引中,而非判断是否在HomeTeam的值列表里,所以几乎所有球队都会进入else分支,导致仅生成Ball PossessionMatch_A/MP列 - 数据重复:每次循环生成对应球队的所有匹配行,concat后每行会出现多次(和该行涉及的两支球队数量一致)
- 结果收集逻辑缺失:if分支生成的
current_df没有加入df_list3,导致if分支的计算结果完全丢失 - 逻辑冗余:不需要拆分数据再合并,直接在原DataFrame上新增两列即可
修改后实现代码
import pandas as pd # 第一步:先处理时间格式,按比赛时间升序排序,保证后续取历史数据逻辑正确 df['Datetime'] = pd.to_datetime(df['Datetime']) df = df.sort_values('Datetime', ascending=True).reset_index(drop=True) # 初始化两个新列 df['Ball PossessionMatch_H/MP'] = 0.0 df['Ball PossessionMatch_A/MP'] = 0.0 # 逐行计算历史平均控球率 for idx, row in df.iterrows(): # 计算主队的历史平均控球率 home_team = row['HomeTeam'] # 取所有早于当前场次的该队比赛数据 home_history = df[ ((df['HomeTeam'] == home_team) | (df['AwayTeam'] == home_team)) & (df.index < idx) ] if len(home_history) > 0: home_possession_sum = ( home_history[home_history['HomeTeam'] == home_team]['Ball PossessionMatch_H'].sum() + home_history[home_history['AwayTeam'] == home_team]['Ball PossessionMatch_A'].sum() ) df.loc[idx, 'Ball PossessionMatch_H/MP'] = round(home_possession_sum / len(home_history), 2) else: # 首次参赛没有历史数据,可根据需求赋值为NaN或者0 df.loc[idx, 'Ball PossessionMatch_H/MP'] = pd.NA # 计算客队的历史平均控球率 away_team = row['AwayTeam'] away_history = df[ ((df['HomeTeam'] == away_team) | (df['AwayTeam'] == away_team)) & (df.index < idx) ] if len(away_history) > 0: away_possession_sum = ( away_history[away_history['HomeTeam'] == away_team]['Ball PossessionMatch_H'].sum() + away_history[away_history['AwayTeam'] == away_team]['Ball PossessionMatch_A'].sum() ) df.loc[idx, 'Ball PossessionMatch_A/MP'] = round(away_possession_sum / len(away_history), 2) else: df.loc[idx, 'Ball PossessionMatch_A/MP'] = pd.NA # 如果需要恢复原始的降序排列,执行以下代码 df = df.sort_values('Datetime', ascending=False).reset_index(drop=True) print(df)
输出效果示例
Unnamed: 0 Datetime HomeTeam AwayTeam Ball PossessionMatch_H Ball PossessionMatch_A Ball PossessionMatch_H/MP Ball PossessionMatch_A/MP 0 0 2021-05-24 02:30:00 U. De Chile Everton 68 32 50.33 43.5
内容的提问来源于stack exchange,提问作者luka
相关产品推荐
相关产品推荐

