如何对每行多列的值进行排名

问题描述 投票:0回答:2

我有一个包含 4 列的数据框,如下所示:

               index 1   index 2    index 3      index 4
date                                                   
2023-07-14     0.0585     0.0775    -0.0289      0.0069
2023-07-17     0.0585     0.0750    -0.0300      0.0065
2023-07-18     0.0590     0.0729    -0.0311      0.0065
2023-07-19     0.0599     0.0711    -0.0309      0.0067
2023-07-20     0.0803     0.0689    -0.0309      0.0071
2023-07-21     0.0613     0.0677    0.0989       0.0083

我想创建两个新列,分别为“rank 1”和“rank 2”来标识每行具有最大值和第二大值的索引,如下所示:

               index 1   index 2    index 3      index 4   Rank 1    rank 2 
date                                                   
2023-07-14     0.0585     0.0775    -0.0289      0.0069    index 2    index 1
2023-07-17     0.0585     0.0750    -0.0300      0.0065    index 2    index 1
2023-07-18     0.0590     0.0729    -0.0311      0.0065    index 2    index 1
2023-07-19     0.0599     0.0711    -0.0309      0.0067    index 2    index 1
2023-07-20     0.0803     0.0689    -0.0309      0.0071    index 1    index 2
2023-07-21     0.0613     0.0677     0.0989      0.0083    index 3    index 2

我了解了 df.rank 函数,但它似乎只能按列对值进行排名,而不是按行。

python pandas rank
2个回答
0
投票

使用

argpartition
,这将是最有效的方法:

import numpy as np

N = 2
cols = df.columns.to_numpy()
df[[f'Rank {x+1}' for x in range(N)]] = cols[np.argpartition(df.to_numpy(),
                                                             -N)[:, :-N-1:-1]]

输出:

            index 1  index 2  index 3  index 4   Rank 1   Rank 2
date                                                            
2023-07-14   0.0585   0.0775  -0.0289   0.0069  index 2  index 1
2023-07-17   0.0585   0.0750  -0.0300   0.0065  index 2  index 1
2023-07-18   0.0590   0.0729  -0.0311   0.0065  index 2  index 1
2023-07-19   0.0599   0.0711  -0.0309   0.0067  index 2  index 1
2023-07-20   0.0803   0.0689  -0.0309   0.0071  index 1  index 2
2023-07-21   0.0613   0.0677   0.0989   0.0083  index 3  index 2

对于纯pandas方法(但效率低得多),

stack
sort_values
,使用
pivot
进行过滤和重塑:

N = 2

out = df.join(df.stack().sort_values(ascending=False)
   .reset_index(-1)[['level_1']]
   .groupby(level=0).head(N)
   .assign(col=lambda d: 'Rank '+d.groupby(level=0).cumcount().add(1).astype(str))
   .pivot(columns='col', values='level_1')
)

0
投票

这可以通过 apply 和 lambda 函数的组合来完成(经过进一步调查):

    df['rank1']=df.T.apply(lambda x: x.nlargest(1).idxmin())
    df['rank2']=df.T.apply(lambda x: x.nlargest(2).idxmin())
© www.soinside.com 2019 - 2024. All rights reserved.