pandas分组求排序取最大所在行

前段时间有个需求,求iPad所有版本中,数量最多的前五个,并且剩下的的作为其他,刚开始接触pandas还是觉得挺复杂的,后来又有类似的需求,所以总结一下以便之后使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from pandas import DataFrame

df = pd.DataFrame({
'flag': ['a', 'b', 'c', 'd', 'e', 'f'],
'class': ['class1', 'class1', 'class2', 'class2', 'class2', 'class3'],
'no': [1, 2, 3, 4, 5, 6],
'grade': [93, 92, 95, 100, 100, 96]})

df
"""
Out[11]:
class flag grade no
0 class1 a 93 1
1 class1 b 92 2
2 class2 c 95 3
3 class2 d 100 4
4 class2 e 100 5
5 class3 f 96 6
"""

目的:按照class分组,取出grade最大的那行

方式1: 在分组中过滤出最大的行

1
2
3
4
5
6
7
8
9
10
11
12
df.groupby('class')\
.apply(lambda x: x[x['grade'] == x['grade'].max()])

"""
Out[10]:
class flag grade no
class
class1 0 class1 a 93 1
class2 3 class2 d 100 4
4 class2 e 100 5
class3 5 class3 f 96 6
"""

方式2: 先排好序,然后每组取第一个

1
2
3
4
5
6
7
8
9
10
11
12
13

df.sort_values(['grade'], ascending=False)\
.groupby('class')\
.first()

"""
Out[21]:
flag grade no
class
class1 a 93 1
class2 d 100 4
class3 f 96 6
"""

方式3: idxmax

1
2
3
4
5
6
7
8
9
10
11
12
df.iloc[df.groupby('class').grade.idxmax()]

# 思考 iloc 和 loc 的区别?
df.loc[df.groupby('class').grade.idxmax()]

"""
Out[17]:
class flag grade no
0 class1 a 93 1
3 class2 d 100 4
5 class3 f 96 6
"""

注:

  • 方式1与其他两个区别,最大值有重复的,方式1会都取出来,而其他的只取一条
  • 思考 方式2中 iloc 和 loc 的区别
  • 思考 如果不是要取出最大值所在的行,比如要中间值所在的那行呢?
  • 对于方式1, 如果取最大的前3行,可以使用 head(3) 代替 first()