python - 如何计算 pandas 中列的分组加权聚合?
问题描述
我是一名主要的 JS 开发人员,正在尝试使用 pandas 并执行一些数据分析。该分析的一部分包括将球队的比赛表现(赢/输)转换为数字评级(基于胜率)。
TLDR:我正在尝试从 DF 1 到 DF 3。
东风1
| season | opponent | outcome |
-------------------------------------
| 2020 | A | w |
| 2020 | A | l |
| 2020 | B | w |
| 2020 | B | w |
| 2020 | C | l |
| 2020 | C | l |
| 2021 | A | w |
| 2021 | A | w |
| 2021 | B | w |
| 2021 | B | l |
| 2021 | C | w |
| 2021 | C | w |
我需要计算按赛季和对手分组的胜率。
东风2
| season | opponent | win % |
-------------------------------------
| 2020 | A | 50 |
| 2020 | B | 100 |
| 2020 | C | 0 |
| 2021 | A | 100 |
| 2021 | B | 50 |
| 2021 | C | 100 |
之后,我们需要计算每个赛季的收视率。这是通过对同一赛季各队的胜率进行平均来完成的,但需要注意的是,对阵 A 队的胜率是其他球队的两倍。这只是任意公式,实际计算更复杂(不同的对手有不同的权重 - 我需要一种方法将其作为自定义 Lambda 函数或其他东西的一部分传递)但我试图简化这个问题的事情。
东风3
| season | rating |
-------------------------
| 2020 | 50.0 |
| 2021 | 87.5 |
评分计算示例:2020 赛季评分 = A 队 % * 2 + B 队获胜率 % + C 队获胜率 /(队伍总数 + 1)=(50% * 2 + 100% + 0%)/(3 + 1 ) = 50.0
我们如何使用 pandas 从第一个数据帧到最后一个数据帧?我可以使用以下方法获得 DF 2 的版本
df2 = df1.groupby(["season", "opponent"])["outcome"].value_counts(normalize = True).to_frame()
此框架包括不需要的损失百分比,但作为“转换”到 DF 3 的一部分,我是否能够过滤/丢弃它并不重要。
我一直在尝试做类似的事情df2 = df2[df2["outcome"] != "w"]
,或者df2 = df2.query('outcome != "w"')
根据另一个问题的答案删除带有丢失条件的附加行,但无济于事。我怀疑这是因为outcome
是嵌套列。也注意到了这个问题,但我认为我需要一个“通配符”来访问嵌套outcome
列,而不管opponent
.
注意:如果有更有效的方法可以直接从 DF 1 到 DF 3(这看起来很接近但并不完全),我也很乐意探索这些方法。
解决方案
import pandas as pd
df_test = pd.DataFrame(data={'season':[2020]*6 + [2021]*6, 'opponent': ['A', 'A', 'B', 'B', 'C', 'C']*2,
'outcome': ['w', 'l', 'w', 'w', 'l', 'l', 'w', 'w', 'w', 'l', 'w', 'w']})
df_weightage = pd.DataFrame(data={'season':[2020]*3 + [2021]*3, 'opponent': ['A', 'B', 'C']*2,
'weightage': [0.2, 0.3, 0.5, 0.1, 0.2, 0.7]})
print(df_test)
print('='*30)
print(df_weightage)
print('='*35)
def get_pct(data):
return len(data[data == 'w'])/len(data)
def get_rating(data):
return sum(data['win_percentage']*data['weightage'])/len(data)
df_test = df_test.groupby(["season", "opponent"])["outcome"].apply(get_pct).rename('win_percentage').reset_index()
print(df_test)
print('='*45)
df_test = df_test.merge(df_weightage, how= 'left', on=['season', 'opponent'])
print(df_test)
print('='*45)
df_ratings = df_test.groupby(['season'])[['win_percentage', 'weightage']].apply(get_rating).rename('ratings').reset_index()
print(df_ratings)
推荐阅读
- node.js - 如何从 Google Text-to-Speech API(fs.writeFile vs createWriteStream)将文件写入 Firebase Storage?
- c# - 将 0 到 1 之间的 a 标准化为给定的最小值和最大值
- javascript - 将 Calendly 嵌入 React
- html - li元素内的div内的响应img?
- javascript - 使用jQuery的下拉隐藏显示
- javascript - 如何转义作为参数传递的字符串——无效的语法。参数列表后缺少 )
- visual-studio-code - 如何在 VSCode 中找到并覆盖 CREATE FOLDER 的键绑定?
- gitlab - gitlab-runner 无法在 Windows 7 上运行 gui 框架的测试打开
- bootstrap-accordion - 如何初始化动态添加到页面的引导控件?
- python - 读取多个文件,但找出我当前在哪个文件上