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

iezvtpos  于 2023-04-10  发布在  其他
关注(0)|答案(1)|浏览(125)

简介及问题

如果排序基于多个列,并且排序允许并列排序,如何对组内的观察进行排序?
我知道如何使用groupby()方法计算聚合的组级统计数据,我也知道如何使用多列不分组进行排名(参见hereherehere)。主要问题似乎是如何将这两种想法(分组和排名)很好地结合在一起。
This other thread对于如何解决这个问题有一些想法,但是它的结果并不显示哪些行是并列的--它只返回一个秩不断增加的数组,即使值是相同的。

最小可复制示例

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变量进行排名,事情就会变得棘手。使用by this other post建议的方法,我们得到以下结果:

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行。
我甚至试着从this answer中修改解决方案,但当我们有groupby语句时,它不起作用。
回到问题的核心
如果排序基于多个列,并且排序允许并列排序,如何对组内的观察进行排序?

bfhwhh0e

bfhwhh0e1#

不清楚为什么不能将链接解决方案与.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

相关问题