如何在Pandas groupby后获取各科目最优/最差成绩及对应学生?
按科目统计最高分/最低分及对应学生的实现方案
问题场景
现有考试成绩数据表,需统计各科目得分最高和最低的学生及其成绩:
输入表
| Subject | Score | Name |
|---|---|---|
| Math | 27 | Student1 |
| History | 43 | Student2 |
| Math | 44 | Student3 |
| History | 50 | Student1 |
| Science | 7 | Student1 |
| History | 10 | Student3 |
| Science | 43 | Student2 |
期望输出表
| Subject | BestScr | BestStud | WorstScr | WorstStud |
|---|---|---|---|---|
| Math | 44 | Student3 | 27 | Student1 |
| History | 50 | Student1 | 10 | Student3 |
| Science | 43 | Student2 | 7 | Student1 |
用户尝试了以下代码,但无法获取对应学生姓名:
inputTableGrouped = inputTable.groupby(['Subject']) outputTableGrouped['BestScr'] = inputTableGrouped.Score.max() outputTableGrouped['WorstScr'] = inputTableGrouped.Score.min() outputTable = outputTableGrouped.reset_index()
解决方案
方法一:使用groupby.apply提取对应记录
通过groupby的apply方法,在每个科目分组内分别筛选出最高分和最低分的行,再将结果重组为目标格式:
import pandas as pd def get_best_worst(group): # 筛选最高分的行(若有多个同分可调整逻辑,这里取第一个) best = group[group['Score'] == group['Score'].max()].iloc[0] # 筛选最低分的行 worst = group[group['Score'] == group['Score'].min()].iloc[0] return pd.Series({ 'BestScr': best['Score'], 'BestStud': best['Name'], 'WorstScr': worst['Score'], 'WorstStud': worst['Name'] }) # 分组处理并重置索引 outputTable = inputTable.groupby('Subject').apply(get_best_worst).reset_index()
方法二:分别筛选最值行后合并
先分别提取各科目最高分和最低分的数据集,再通过merge合并成目标表:
# 获取各科目最高分数据 best_df = inputTable.loc[inputTable.groupby('Subject')['Score'].idxmax()] best_df = best_df.rename(columns={'Score': 'BestScr', 'Name': 'BestStud'}) # 获取各科目最低分数据 worst_df = inputTable.loc[inputTable.groupby('Subject')['Score'].idxmin()] worst_df = worst_df.rename(columns={'Score': 'WorstScr', 'Name': 'WorstStud'}) # 合并两个数据集 outputTable = pd.merge(best_df[['Subject', 'BestScr', 'BestStud']], worst_df[['Subject', 'WorstScr', 'WorstStud']], on='Subject')
补充说明
如果存在同科目同分的情况,上述方法默认取第一个出现的学生。若需要显示所有同分学生,可将iloc[0]改为用str.join()拼接姓名,例如:best['Name'].str.join(', ')(需确保分组后筛选结果是DataFrame)。
内容的提问来源于stack exchange,提问作者myooons
相关产品推荐
相关产品推荐

