看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
在统计学生成绩时,会对学生的成绩进行排名(或许可能不需要),暂且理解为一项体育比赛项目的小组赛吧。往往排名会在分组内进行,标记每行数据在分组内的排名,今天我们就来实现这个需求。
我们还是继续用的我们的学生成绩表示例数据集吧:
import pandas as pd
df = pd.read_csv('https://gairuo.com/file/data/team.csv')
df.head()
'''
name team Q1 Q2 Q3 Q4
0 Liver E 89 21 24 64
1 Arry C 36 37 37 57
2 Ack A 57 60 18 84
3 Eorge C 93 96 71 78
4 Oah D 65 49 61 86
'''
team 列为分组,我们需要增加一列学生的总成绩,然后在增加一列学生总成绩在分组内的排名。
首先分析需求,这个需求有两个部分:
增加总成绩列这个简单,用 sum(1),传入的 1 为 axis 参数的值,按行进行计算,当然行上有非成绩列不需计算,我对 sum() 传入 numeric_only=True 进行过滤:
df.assign(total=df.sum(1, numeric_only=True)).head()
'''
name team Q1 Q2 Q3 Q4 total
0 Liver E 89 21 24 64 198
1 Arry C 36 37 37 57 167
2 Ack A 57 60 18 84 219
3 Eorge C 93 96 71 78 338
4 Oah D 65 49 61 86 261
'''
这样就计算出了总成绩,接下来就是完成第二个部分。
既然是按组排名,我们就需要用 groupby 进行分组,然后不需要对分组进行聚合(不用 agg),也不需要进行筛选(不用 filter),没错就用它 transform() 。transform() 可以对分组的值按分组进行计算,然后返回一个和分组数据相同长度的数据。
在 transform() 中应用的排名方法是 pd.Series.rank(),根据需求,排序是由高到低的,需要传入 ascending=False
。排名方法(method: 'str' = 'average'
)我们使用默认的,当然可以根据需求,传入其他排名方法。最后还要将排名转为整型。最后代码为:
(
df.assign(total=df.sum(1, numeric_only=True))
.assign(rank=lambda x: x.groupby('team').total.transform('rank', ascending=False).astype(int))
.style # 技巧:可以看到全部数据
)
'''
name team Q1 Q2 Q3 Q4 total rank
0 Liver E 89 21 24 64 198 10
1 Arry C 36 37 37 57 167 16
2 Ack A 57 60 18 84 219 7
3 Eorge C 93 96 71 78 338 1
4 Oah D 65 49 61 86 261 7
.. ... ... .. .. .. .. ... ...
'''
另外,我们可以不使用 transform() ,分组后对指定列直接调用 rank() 简化代码,得到同样的结果:
(
df.assign(total=df.sum(1, numeric_only=True))
.assign(rank=lambda x: x.groupby('team').total.rank(ascending=False).astype(int))
)
这样就实现了需求,在保持原数据顺序不变的情况为按分组对数据的排名进行标记。
(完)
更新时间:2024-08-18 15:38:34 标签:python pandas 分组 名次