Pandas处理棒球比赛数据:计算Run_diff得分差与Win_Loss胜负列
Pandas计算棒球比赛得分差与胜负标记的实现方案
你的原始数据符合「每场比赛的两支对战队伍连续排列,每2行对应1场比赛」的结构,可通过向量化操作实现需求,无循环、无链式索引警告,逻辑更简洁。
实现步骤
1. 预处理与比赛分组
先按日期排序并重置索引,确保数据顺序正确,再按「每2行一组」生成临时比赛分组ID,避免不同比赛的分数错误关联:
import pandas as pd import numpy as np # 原始数据 df = pd.DataFrame({'Date': [402, 402, 402, 402, 403, 403, 404, 404], 'Team' : ['SFO', 'ARI', 'CUB', 'STL', 'NYY', 'SEA', 'OAK', 'LAA'], 'Final' :[4, 6, 2, 5, 7, 2, 1, 2]}) # 按日期排序并重置索引,避免原索引混乱 df = df.sort_values('Date', ignore_index=True) # 生成临时比赛分组ID:每连续2行属于同一场比赛 df['match_id'] = np.arange(len(df)) // 2
2. 计算得分差Run_diff
利用「同一场比赛的总得分 = 两队得分之和」的特性,单队得分差 = 自身得分 - 对手得分,等价于 2*自身得分 - 同组总得分,无需额外移位操作:
# 计算同一场比赛的总得分 group_score_sum = df.groupby('match_id')['Final'].transform('sum') # 计算得分差 df['Run_diff'] = 2 * df['Final'] - group_score_sum
3. 计算胜负标记Win_Loss
规则为得分差大于0则获胜(标记1),否则失败(标记0):
df['Win_Loss'] = (df['Run_diff'] > 0).astype(int)
4. 清理临时列
删除仅用于分组的match_id列,得到最终结果:
df = df.drop(columns='match_id')
效果验证
运行后得到的df与你给出的df_expected完全一致。
原方法问题说明
- 原逻辑使用全局
shift未按比赛分组,且仅对奇偶行中的奇数行计算差值,偶数行赋值为0,未实现反向得分差计算 - 原方法通过循环逐行修改值属于链式索引操作,会触发
SettingWithCopyWarning警告,且效率远低于向量化操作
内容的提问来源于stack exchange,提问作者chasedcribbet
相关产品推荐
相关产品推荐

