在Pandas中使用组内的多个列进行排名,允许并列排名



简介与问题

如果排名基于不止一列,并且排名允许并列排名,我如何在组内对观察结果进行排名?

我知道如何使用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变量进行分组,并使用Var1Var2变量进行排名。因此,我希望输出看起来像这样:

#    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变量进行分组,并使用Var1Var2变量进行排名,事情就变得复杂了。使用另一篇文章建议的方法,我们得到了以下结果:

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

请注意,Var1Var2的第一行和第二行具有相同的值,但是第一行排名为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

相关内容

  • 没有找到相关文章

最新更新