简介与问题
如果排名基于不止一列,并且排名允许并列排名,我如何在组内对观察结果进行排名?
我知道如何使用groupby()
方法计算聚合的组级统计信息,我还知道如何使用不包含组的多列进行排名(参见这里,这里和这里)。主要的问题似乎是同时得到这两个想法(分组& &;排名)玩得很好。
另一个线程有一些关于如何解决这个问题的想法,但是它的结果并没有告诉你哪些行是捆绑的——它只是返回一个不断增加的秩的数组,即使值是相同的。我在下面的示例中更详细地描述了这个问题。
最小可复制示例
import pandas as pd
df = pd.DataFrame({'row_id':[1,2,3,4,5,6,7,8,9,10],
'Group':[1,1,1,1,1,2,2,2,2,2],
'Var1':[100,100,100,200,200,300,300,400,400,400],
'Var2':[5,5,6,7,8,1,1,2,2,3]})
print(df)
# row_id Group Var1 Var2
# 0 1 1 100 5
# 1 2 1 100 5
# 2 3 1 100 6
# 3 4 1 200 7
# 4 5 1 200 8
# 5 6 2 300 1
# 6 7 2 300 1
# 7 8 2 400 2
# 8 9 2 400 2
# 9 10 2 400 3
在上面的情况下,我想使用Group
变量进行分组,并使用Var1
和Var2
变量进行排名。因此,我希望输出看起来像这样:
# row_id Group Var1 Var2 Rank
# 0 1 1 100 5 1
# 1 2 1 100 5 1
# 2 3 1 100 6 3
# 3 4 1 200 7 4
# 4 5 1 200 8 5
# 5 6 2 300 1 1
# 6 7 2 300 1 1
# 7 8 2 400 2 3
# 8 9 2 400 2 3
# 9 10 2 400 3 5
我已经试过了
使用上面示例中的数据,如果我想使用Group
变量进行分组,并且仅基于Var1
列进行排名,这将非常容易:
df['Rank_Only_Var1'] = df.groupby('Group')['Var1'].rank(method='min', ascending=True)
print(df)
# row_id Group Var1 Var2 Rank_Only_Var1
# 0 1 1 100 5 1.0
# 1 2 1 100 5 1.0
# 2 3 1 100 6 1.0
# 3 4 1 200 7 4.0
# 4 5 1 200 8 4.0
# 5 6 2 300 1 1.0
# 6 7 2 300 1 1.0
# 7 8 2 400 2 3.0
# 8 9 2 400 2 3.0
# 9 10 2 400 3 3.0
然而,如果我想使用Group
变量进行分组,并使用Var1
和Var2
变量进行排名,事情就变得复杂了。使用另一篇文章建议的方法,我们得到了以下结果:
df = df.sort_values(['Var1', 'Var1'], ascending=[True, True])
df['overall_rank'] = 1
df['overall_rank'] = df.groupby(['Group'])['overall_rank'].cumsum()
print(df)
# row_id Group Var1 Var2 overall_rank
# 0 1 1 100 5 1
# 1 2 1 100 5 2
# 2 3 1 100 6 3
# 3 4 1 200 7 4
# 4 5 1 200 8 5
# 5 6 2 300 1 1
# 6 7 2 300 1 2
# 7 8 2 400 2 3
# 8 9 2 400 2 4
# 9 10 2 400 3 5
请注意,Var1
和Var2
的第一行和第二行具有相同的值,但是第一行排名为1,第二行排名为2。这两行不应该有不同的等级。它们的排名应该是相同且并列的,因为排名所基于的值是相同且并列的。这个问题也发生在第6行&7以及与行8 &9 .
我甚至试着从这个答案中适应解决方案,但当我们有一个groupby
声明时,它不起作用。
回到问题的核心
如果排名基于不止一列,并且排名允许并列排名,我如何在组内对观察结果进行排名?
不清楚为什么不能使用.groupby
链接解决方案
您还可以替换.apply
以获得更好的性能:
(df.assign(key = list(map(tuple, df[['Var1', 'Var2']].values)))
.groupby('Group')['key'].rank('dense'))
0 1.0
1 1.0
2 2.0
3 3.0
4 4.0
5 1.0
6 1.0
7 2.0
8 2.0
9 3.0
Name: key, dtype: float64