今天遇到一个问题:厂家有N个产品,每个产品有M家门店销售,厂家需要快速找出每个产品销售最好的前5名门店。 这个需求类似找出“各科成绩前5名的学生”。简单试了一下,可以使用groupby+rank解决,详细如下:
一、rank()函数简介
def rank(self: FrameOrSeries,
axis: Any = 0,
method: str = "average",
numeric_only: Optional[bool] = None,
na_option: str = "keep",
ascending: bool = True,
pct: bool = False) -> FrameOrSeries
说明:
1、self: FrameOrSeries。说明该函数可以处理frame或Series类型数据的排名。
2、axis: Any = 0。默认是0,按行排名。窃个图说明一下吧
3、
method : {‘average’, ‘min’, ‘max’, ‘first’} 默认值 average。
如果分数为98,97,97,96,95,94,则各个方式排名的说明和结果如下:
first : 按值在原始数据中的出现顺序分配排名。 排序结果:1,2,3,4,5,6
average :在相等分组中,为各个值分配平均排名。 排序结果:1,2.5, 2.5, 4, 5 ,6
min :使用整个分组的最小排名 排序结果:1,2,2,4,5,6
max :使用整个分组的最大排名 排序结果:1,3,3,4,5,6
4、numeric_only: Optional[bool] = None 。 如果设置为True,则只对数字有效
5、na_option: str = "keep" 。默认针对空值的处理,不排名;如果设置na_option='bottom',则空值为最后一名。
6、ascending: bool = True。 默认数值最小的为第一名,如果需要数值最大的为第一名,则设置:ascending=False.
7、 pct: bool = False。 排名按百分比进行,名次最高者为1,其他为名次占最高名次的百分比,如例第6名为显示为1,第1名显示为1/6,即0.16666……
二、需要处理的数据
三、使用的脚本
Step1: 增加排名列,对所有学生进行排名
book
= pd
.read_excel('e:/dan/2.xlsx')
grade
= pd
.DataFrame(book
)
grade
= grade
.sort_values(by=['kemu', 'fenshu'], ascending=False)
grade
['paiming'] = grade
.groupby('kemu')['fenshu'].rank(method='first', ascending=False)
print(grade
) 结果:
kemu stu fenshu paiming
30 math z4 98 1.0
21 math z1 85 2.0
22 math z7 85 3.0
17 math z8 74 4.0
【注意】
对原数据先进行排序是必要的,否则显示出的结果不会按科目和分数排序。
Step2: 再筛选Topn,这里以Top2为例。
Top2
= grade
[grade
['paiming'] <= 2]
print(Top2
)
结果:
kemu stu fenshu paiming
30 math z4 98 1.0
21 math z1 85 2.0
22 math z7 85 3.0
17 math z8 74 4.0
10 math z2 65 5.0
27 english z3 95 1.0
28 english z7 95 2.0
25 english z6 88 3.0
23 english z2 85 4.0
18 english z5 77 5.0
OK,仅此,The End!