使用Pandas按NOC分组计算1996年奥运会前后平均奖牌数的方法
问题核心原因
你之前的代码逻辑存在三个核心错误:
- 第一步先对全量数据做了
NOC维度的总奖牌数聚合,已经把原始数据中Edition(年份)的维度信息完全丢弃,后续没有办法再按时间条件拆分计算- 写的
np.mean(total_medal_count.Medal_Count)本质是计算了所有国家总奖牌数的全局平均值,不是每个NOC自己的分组指标,本身就不符合统计逻辑- 后续的
where筛选逻辑把两个不同粒度的数据框混在了一起:判断条件用的是原始的逐行奖牌记录数据,而赋值的目标是聚合后的国家级统计值,两边行数、维度完全不匹配,自然无法正常运行。
正确实现方案
根据你需要的“按NOC分组、分别计算1996年前后每届奥运会的平均奖牌数”的需求,有两种常用的实现方式:
方案1:拆分计算再合并(可读性最高,适合新手)
逻辑是先按时间拆分原始数据,分别计算两个区间内的分组均值,最后按NOC拼接,不容易写错:
# 1. 按时间拆分原始数据(按需调整不等号,决定1996当届算在哪一组) before_1996 = olympics_df[olympics_df['Edition'] < 1996] after_1996 = olympics_df[olympics_df['Edition'] >= 1996] # 2. 分别计算每个NOC在对应时间区间内,每一届奥运会的奖牌总数 before_medal_each_edition = before_1996.groupby(['NOC', 'Edition'])['Medal'].count().reset_index() after_medal_each_edition = after_1996.groupby(['NOC', 'Edition'])['Medal'].count().reset_index() # 3. 按NOC分组,对单届奖牌数求平均,生成对应列 before_avg = before_medal_each_edition.groupby('NOC')['Medal'].mean().reset_index(name='Average Before 1996') after_avg = after_medal_each_edition.groupby('NOC')['Medal'].mean().reset_index(name='Average After 1996') # 4. 按NOC合并两个结果,未参与某段时间赛事的NOC对应值会自动填充为NaN result_df = pd.merge(before_avg, after_avg, on='NOC', how='outer') # 如果需要把无成绩的NOC的均值填充为0,可执行下面这行 # result_df = result_df.fillna(0)
方案2:单步聚合(运行效率更高,适合大数据量)
直接通过给原始数据打时间标签,用pivot_table一次完成两级聚合,不需要多次拆分数据:
# 给每一行奖牌记录打上对应的时间区间标签 olympics_df['time_phase'] = np.where( olympics_df['Edition'] < 1996, 'Average Before 1996', 'Average After 1996' ) # 直接聚合生成目标表:先算每届每个NOC的奖牌数,再按NOC、时间区间求平均 result_df = olympics_df.pivot_table( index='NOC', columns='time_phase', values='Medal', # 聚合逻辑:先按Edition分组算每届奖牌数,再求均值 aggfunc=lambda edition_group: edition_group.groupby(level='Edition').count().mean() ).reset_index()
注意事项
- 上面的计算逻辑默认是计算每个NOC在对应时间区间内,每届奥运会的平均获奖数,和你之前统计总奖牌数的维度完全对齐
- 如果你的“平均值”需求是其他维度(比如算平均奖牌占比、单运动员平均获奖数),只需要调整最后一步的
aggfunc逻辑即可,不需要改动整体框架
内容的提问来源于stack exchange,提问作者Wiseface
相关产品推荐
相关产品推荐

