如何在pandas中计算列的分组加权聚合,实现赛事胜率到赛季评分转换
解决方案
问题原因分析
你之前的过滤操作失败是因为
groupby+value_counts返回的结果中,outcome是多级索引的层级之一,并非数据列,所以直接按列过滤会报错。返回结果的索引默认是[season, opponent, outcome]三级,数值列存储的是占比。
分步实现方案(DF1→DF2→DF3)
步骤1:正确生成仅包含胜率的DF2
# 把outcome的w/l结果从索引转成列,直接提取胜场占比就是胜率 df2 = df1.groupby(["season", "opponent"])["outcome"].value_counts(normalize=True).unstack() # 取w列作为胜率,没有胜场的对阵默认填充0,重命名列后重置索引 df2 = df2.get("w", 0).reset_index(name="win_rate")
步骤2:支持自定义权重的赛季评分计算(生成DF3)
支持传入自定义Lambda函数实现权重逻辑,完全匹配你给出的评分公式:
# weight_rule参数可传入自定义Lambda调整不同对手的权重 def calculate_season_score(group, weight_rule=lambda oppo: 2 if oppo == "A" else 1): group["weight"] = group["opponent"].apply(weight_rule) # 加权平均计算逻辑和示例公式完全对齐:权重总和 = A队2 + 其他队各1 = 队伍总数 + 1 total_weighted_win = (group["win_rate"] * group["weight"]).sum() total_weight = group["weight"].sum() return total_weighted_win / total_weight # 按赛季分组计算总评分,得到最终DF3 df3 = df2.groupby("season").apply(calculate_season_score).reset_index(name="season_score")
更高效的一步到位实现(无需生成中间DF2)
如果不需要用DF2做其他分析,可以直接从原始DF1计算得到DF3,减少内存占用:
def calc_score_from_raw(group, weight_rule=lambda oppo: 2 if oppo == "A" else 1): # 直接计算当前赛季每个对手的胜率 oppo_win_rate = group.groupby("opponent")["outcome"].apply(lambda x: (x == "w").mean()) # 应用权重规则计算加权分 weights = oppo_win_rate.index.to_series().apply(weight_rule) return (oppo_win_rate * weights).sum() / weights.sum() df3 = df1.groupby("season").apply(calc_score_from_raw).reset_index(name="season_score")
内容的提问来源于stack exchange,提问作者Alvin Teh
相关产品推荐
相关产品推荐

