Python Pandas:计算选手身份动态切换的多列滚动平均值
修正网球选手滚动发球得分平均值计算代码
问题背景
你的网球数据集中选手会在P1和P2身份间切换,直接按P1/P2分组计算滚动平均会因为同一选手跨列分布导致索引冲突,出现ValueError: cannot reindex from a duplicate axis错误。
原始数据示例
假设你的数据结构如下:
| Date | P1 | P2 | P1_1stWon | P2_1stWon |
|---|---|---|---|---|
| 2023-01-01 | A | B | 8 | 6 |
| 2023-01-02 | B | A | 7 | 9 |
| 2023-01-03 | A | C | 10 | 5 |
| 2023-01-04 | C | A | 6 | 8 |
期望输出
需要得到每个选手对应身份下的滚动发球得分平均值(以窗口大小2为例):
| Date | P1 | P2 | P1_1stWon | P2_1stWon | P1_rolling_avg | P2_rolling_avg |
|---|---|---|---|---|---|---|
| 2023-01-01 | A | B | 8 | 6 | 8.0 | 6.0 |
| 2023-01-02 | B | A | 7 | 9 | 6.5 | 8.5 |
| 2023-01-03 | A | C | 10 | 5 | 9.5 | 5.0 |
| 2023-01-04 | C | A | 6 | 8 | 5.5 | 8.5 |
修正代码
import pandas as pd # 读取并预处理数据 df = pd.read_csv('tennis_data.csv') df['Date'] = pd.to_datetime(df['Date']) # 1. 将宽格式数据转为长格式,整合所有选手的参赛记录 long_format = pd.melt( df, id_vars=['Date'], value_vars=['P1', 'P2'], var_name='Player_Role', value_name='Player_Name' ) # 匹配对应角色的发球得分 long_format['1stWon'] = long_format.apply( lambda x: df.loc[x.name, f"{x['Player_Role']}_1stWon"], axis=1 ) # 2. 按选手分组计算滚动平均值(窗口大小可自行调整) long_format['rolling_avg'] = long_format.groupby('Player_Name')['1stWon'].rolling( window=2, min_periods=1, on='Date' ).mean().reset_index(level=0, drop=True) # 3. 拆分回原角色的滚动平均并合并到原数据 p1_avg = long_format[long_format['Player_Role'] == 'P1']['rolling_avg'].rename('P1_rolling_avg') p2_avg = long_format[long_format['Player_Role'] == 'P2']['rolling_avg'].rename('P2_rolling_avg') final_df = pd.concat([df, p1_avg, p2_avg], axis=1) # 输出结果 print(final_df)
关键逻辑说明
- 长格式转换:用
pd.melt把P1/P2列拆分为角色和选手名,让同一选手的所有参赛记录(无论作为P1还是P2)都归到同一分组下,解决跨列分组的问题。 - 滚动平均计算:基于
Date排序后按选手分组计算滚动平均,min_periods=1确保第一条记录能输出自身数值。 - 合并回原数据:将长格式中对应
P1/P2的滚动平均拆分出来,与原数据按索引合并,保证结果行与原数据完全对应。
内容的提问来源于stack exchange,提问作者user19446980
相关产品推荐
相关产品推荐

