如何在Pandas中按posteam分组并结合penalty_team条件聚合数据
问题描述
现有如下DataFrame:
import pandas as pd df = pd.DataFrame([ {'posteam': 'NYJ', 'defteam': 'BAL', 'penalty': 1, 'penalty_team': 'NYJ', 'penalty_yards': 10}, {'posteam': 'NYJ', 'defteam': 'BAL', 'penalty': 1, 'penalty_team': 'BAL', 'penalty_yards': 5}, {'posteam': 'BAL', 'defteam': 'NYJ', 'penalty': 0, 'penalty_team': None, 'penalty_yards': 0}, {'posteam': 'BAL', 'defteam': 'NYJ', 'penalty': 1, 'penalty_team': 'NYJ', 'penalty_yards': 15}])
需求:按posteam中的球队统计其所有犯规次数和码数(无论该球队是进攻方还是防守方,只要penalty_team等于该球队,就计入统计),期望输出如下:
| posteam | penalty | penalty_yards |
|---|---|---|
| NYJ | 2 | 25 |
| BAL | 1 | 5 |
当前使用的聚合代码仅统计了球队作为进攻方时的犯规,结果不符合预期:
df.groupby(['posteam']).agg({ 'penalty': 'sum', 'penalty_yards': 'sum' })
输出结果:
| posteam | penalty | penalty_yards |
|---|---|---|
| NYJ | 2 | 15 |
| BAL | 1 | 15 |
解决方案
方法一:筛选有效行后按犯规球队聚合,对齐原球队列表
核心逻辑是:先过滤掉无犯规的行(penalty_team为空的行),然后按penalty_team分组统计犯规数据,最后将结果索引对齐到原posteam的所有球队,确保所有目标球队都出现在结果中。
import pandas as pd # 过滤掉无犯规的行 filtered_df = df[df['penalty_team'].notna()] # 按犯规球队聚合统计 result = filtered_df.groupby('penalty_team').agg( penalty=('penalty', 'sum'), penalty_yards=('penalty_yards', 'sum') ).rename_axis('posteam') # 将索引名改为posteam,匹配期望输出 # 对齐原posteam的所有球队,填充无犯规的情况为0 result = result.reindex(df['posteam'].unique()).fillna(0).astype(int) print(result)
运行后输出:
penalty penalty_yards posteam NYJ 2 25 BAL 1 5
方法二:使用条件聚合(无需过滤行)
直接在聚合时加入条件判断,仅统计penalty_team与分组球队一致的行:
result = df.groupby('posteam').agg( penalty=('penalty', lambda x: x[df['penalty_team'] == x.name].sum()), penalty_yards=('penalty_yards', lambda x: x[df['penalty_team'] == x.name].sum()) ) print(result)
该方法通过lambda函数在聚合时筛选出当前分组球队(x.name即当前posteam值)作为penalty_team的行,再求和,同样能得到期望结果。
内容的提问来源于stack exchange,提问作者jwald3
相关产品推荐
相关产品推荐

