基于Pandas实现分性别、年龄组和项目取前3名(含并列)选手统计
解决运动数据分性别、年龄组、项目取前3获奖者(含并列)的问题
问题分析
你的需求是按性别、年龄组、项目筛选各分组下的前3名(含并列成绩的所有选手),但原代码存在几个关键问题:
- 错误将成绩列(
run1000)加入分组键,导致分组逻辑混乱 - 多余的
agg("mean")操作无意义,反而破坏了原始成绩数据 - 排序和取数逻辑颠倒(跑步成绩越短越好,应升序排序后取前N,而非降序后取最小)
正确实现方案
假设你的数据结构包含以下字段:
sex: 性别(如'ж'代表女孩,'м'代表男孩)year: 年龄组event: 项目名称(若run1000是成绩列,需单独的项目列;若run1000本身是项目,可调整分组键)fullName: 选手姓名run1000: 1000米跑成绩(数值越小越好)
情况1:每个选手在对应分组下只有1个成绩
直接按性别、年龄组、项目分组,组内对成绩升序排序,用rank标记排名后保留排名≤3的所有选手(含并列):
import pandas as pd # 核心筛选函数 def get_top3(group): # 按成绩升序排序,并列成绩取相同最小排名 group['rank'] = group['run1000'].rank(method='min', ascending=True) # 保留前3名及并列选手 return group[group['rank'] <= 3].drop(columns='rank') # 按分组应用筛选逻辑 result = data.groupby(['sex', 'year', 'event'], group_keys=False).apply(get_top3) # 输出结果 print(result)
情况2:每个选手在对应分组下有多个成绩(需先取最好成绩)
若同一选手在同一年龄组、项目有多次成绩,先取其最好成绩,再进行排名筛选:
# 第一步:取每个选手在对应分组下的最好成绩 best_scores = data.groupby(['sex', 'year', 'event', 'fullName'])['run1000'].min().reset_index() # 第二步:按分组筛选前3名(含并列) result = best_scores.groupby(['sex', 'year', 'event'], group_keys=False).apply(get_top3) print(result)
关键说明
rank(method='min'):确保并列成绩的选手获得相同的最小排名,比如两个选手都是第2名,后续选手直接排第4,这样排名≤3的结果会包含所有并列前3的选手- 若成绩是数值越大越好(如跳远、跳高),只需将
ascending=True改为ascending=False - 若只有
run1000一个项目,可去掉event分组键,仅按sex和year分组
内容的提问来源于stack exchange,提问作者AlexAnderson
相关产品推荐
相关产品推荐

