Python案例如何用Pandas做数据分组排名

wen python案例 1

Python案例:如何用Pandas做数据分组排名(附实战代码)

目录导读

  1. 为什么需要数据分组排名?
  2. Pandas分组排名核心函数:groupby() + rank()
  3. 6种不同排名方法详解(average、min、max、dense、first、ordinal)
  4. 实战案例:学生成绩分组排名
  5. 进阶技巧:多列分组、跨组排名、条件排名
  6. 常见错误与解决方案
  7. 问答环节:高频问题解答

为什么需要数据分组排名?

在日常数据分析中,我们经常需要按某个类别分组后,再对组内的数据进行排名。

Python案例如何用Pandas做数据分组排名

  • 按班级对学生的成绩进行排名
  • 按部门对销售人员的业绩进行排名
  • 按月份对产品销量进行排名

单纯使用df.sort_values()只能进行全局排名,而分组排名能反映出“组内竞争”的实际情况,这是数据分析中的高频需求。


Pandas分组排名核心函数:groupby() + rank()

Pandas提供了rank()方法,配合groupby()可以实现分组排名,核心语法:

df['排名'] = df.groupby('分组列')['排序列'].rank(method='排名方法', ascending=True/False)
  • 分组列:按哪个字段分组(如班级、部门)
  • 排序列:对哪个数值字段排名(如成绩、销售额)
  • method:排名方法(下文详述)
  • ascending=True:升序排名(数值越小排名越前);False为降序

6种不同排名方法详解(附效果对比)

Pandas的rank()提供了6种排名方法,选择哪种取决于业务需求:

method参数 效果说明 适用场景
'average'(默认) 相同值取平均排名(如并列第2和第3,均排名2.5) 学术统计、需要保留小数位
'min' 相同值取最小排名(并列第2则均排第2) 竞技排名,鼓励并列
'max' 相同值取最大排名(并列第2则均排第3) 严格排序,不鼓励并列
'dense' 密集排名(并列后下一名紧接,如1,1,2) 需要连续整数排名
'first' 按出现顺序排名,相同值先出现者排名靠前 时间优先的场景
'ordinal' 类似'first',但返回整数 'first'几乎相同

演示代码

import pandas as pd
data = {'班级': ['A','A','A','B','B','B'],
        '成绩': [90, 85, 90, 88, 95, 88]}
df = pd.DataFrame(data)
for method in ['average','min','max','dense','first']:
    df[method] = df.groupby('班级')['成绩'].rank(method=method, ascending=False)
print(df)

输出结果清晰展示了不同方法如何影响并列值的排名。


实战案例:学生成绩分组排名

场景:某学校有3个班级,需按班级对数学成绩进行降序排名,相同分数按语文成绩排名。

完整代码

import pandas as pd
# 构造数据
data = {
    '班级': ['A','A','A','A','B','B','B','C','C','C'],
    '姓名': ['张三','李四','王五','赵六','孙七','周八','吴九','郑十','冯十一','陈十二'],
    '数学': [92, 88, 92, 85, 90, 90, 88, 95, 87, 87],
    '语文': [85, 90, 88, 82, 89, 85, 90, 82, 91, 86]
}
df = pd.DataFrame(data)
# 分组排名:按班级分组,先按数学降序,相同则按语文降序
df['数学排名'] = df.groupby('班级')['数学'].rank(method='dense', ascending=False)
# 处理并列:数学同分时按语文排名
df['综合排名'] = df.groupby('班级').apply(
    lambda x: x[['数学','语文']].apply(tuple, axis=1).rank(method='dense', ascending=False)
).reset_index(level=0, drop=True)
print(df.sort_values(['班级','综合排名']))

结果解读

  • 班级A中,张三和王五数学同分92,但王五语文88>张三85,因此王五排名第1
  • 班级C中,冯十一和陈十二数学同分87,冯十一语文91>陈十二86,因此冯十一排名第1

进阶技巧:多列排名与条件排名

1 多列分组排名

按两个维度分组(如年级+班级):

df.groupby(['年级','班级'])['成绩'].rank(ascending=False)

2 跨组全局排名

有时需要组内排名后,再结合全局数据计算,例如先分组排名,再筛选各组Top 3:

df['组内排名'] = df.groupby('班级')['成绩'].rank(method='dense', ascending=False)
top3 = df[df['组内排名'] <= 3]

3 条件分组排名

只对满足条件的行进行排名(如只排成绩合格的学生):

mask = df['成绩'] >= 60
df.loc[mask, '及格排名'] = df[mask].groupby('班级')['成绩'].rank(ascending=False)

常见错误与解决方案

错误1KeyError: '分组列'
原因:分组列名拼写错误或不存在
解决:检查df.columns确认列名

错误2:排名结果出现NaN
原因:分组列存在缺失值,导致某些组无法排名
解决:先使用df.dropna(subset=['分组列'])清理

错误3:期望整数排名但得到小数
原因:使用了默认method='average'
解决:改用method='dense'method='min'

错误4:排名顺序相反
原因ascending参数设置错误
解决:降序排名用ascending=False


问答环节:高频问题解答

Q1:分组排名和全局排名有什么区别?
A:全局排名基于整个数据集排序(如全校排名),分组排名基于组内排序(如班级排名),Pandas中df['成绩'].rank()是全局排名,df.groupby('班级')['成绩'].rank()是分组排名。

Q2:如果数据有几十万行,分组排名性能如何?
A:Pandas的groupby+rank基于Cython优化,百万级数据可轻松处理,若超千万行,建议先sort_values再手动分组计算,或使用Dask。

Q3:如何实现类似“排名百分位数”(即百分比排名)?
A:在rank()中设置pct=True即可得到百分比排名(0~1之间)。

df['百分比排名'] = df.groupby('班级')['成绩'].rank(pct=True, ascending=False)

Q4:分组排名后,为什么索引会乱?
Agroupby()会保留原索引,如需重置,加.reset_index(drop=True)

Q5:能否实现“窗口排名”(如只对近7天数据排名)?
A:可以先用rolling()计算时间窗口,再结合applyrank(),但更推荐用sort_values后手动分组。


本文为原创内容,基于实际开发经验撰写,结合搜索引擎信息进行重组优化,希望能帮助您快速掌握Pandas分组排名技巧,如需转载,请保留出处。

抱歉,评论功能暂时关闭!