Pandas DataFrame行间计算 班级考试表现得分计算及排名实现方法
实现方案
直接计算班级得分与排名
用pandas的链式操作即可一步完成计算,无需创建多个中间DataFrame:
import pandas as pd # 原始数据读入示例,如果你已有df可跳过这部分 data = [ ['a','First','Bad','t1'],['a','First','Bad','t2'],['a','First','Good','t2'], ['b','Second','Bad','t1'],['c','First','Good','t3'],['c','First','Bad','t2'], ['d','Third','Bad','t1'],['d','Third','Bad','t4'],['d','Third','Good','t4'], ['e','Fourth','Good','t3'],['e','Fourth','Good','t2'],['f','Third','Good','t1'], ['g','Fourth','Good','t4'],['g','Fourth','Bad','t3'] ] df = pd.DataFrame(data, columns=['Student','Class','Result','Exam']) # 核心计算逻辑 class_rank = ( # 第一步:按学生+班级分组计算个人得分 df.groupby(['Student', 'Class'], as_index=False) .apply(lambda x: (x['Result'] == 'Good').sum() / len(x), include_groups=False) .rename(columns={0: 'Score'}) # 第二步:按班级分组计算班级平均分并生成排名 .groupby('Class', as_index=False) .agg(ClassScore=('Score', 'mean')) .sort_values('ClassScore', ascending=False, ignore_index=True) .assign(Rank=lambda x: x['ClassScore'].rank(ascending=False, method='min').astype(int)) )
输出结果示例:
| Class | ClassScore | Rank |
|---|---|---|
| Fourth | 0.75 | 1 |
| Third | 0.665 | 2 |
| First | 0.415 | 3 |
| Second | 0.0 | 4 |
保留学生维度的完整结果
如果你需要同时保留每个学生的个人得分、对应班级得分和排名,可以用transform方法直接在同一张表中生成字段:
df_full = ( df.groupby(['Student', 'Class'], as_index=False) .apply(lambda x: (x['Result'] == 'Good').sum() / len(x), include_groups=False) .rename(columns={0: 'Score'}) .assign( ClassScore = lambda x: x.groupby('Class')['Score'].transform('mean'), ClassRank = lambda x: x['ClassScore'].rank(ascending=False, method='min').astype(int) ) .sort_values('ClassRank', ignore_index=True) )
输出结果和你给出的示例结构一致,同时额外增加了班级排名字段。
可视化展示
如果需要更直观的对比班级表现,可以用matplotlib生成柱状图:
import matplotlib.pyplot as plt plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题 class_rank.plot(kind='bar', x='Class', y='ClassScore', legend=False, color='#3498db') plt.xticks(rotation=0) plt.ylabel('班级平均得分') plt.title('班级考试表现排名') # 标注每个班级的得分与排名 for idx, row in class_rank.iterrows(): plt.text(idx, row['ClassScore'] + 0.02, f'得分:{row["ClassScore"]:.3f}\n排名:{row["Rank"]}', ha='center') plt.ylim(0, 1.15) plt.show()
内容的提问来源于stack exchange,提问作者johnnydoe
相关产品推荐
相关产品推荐

