我有一个包含 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 函数,但它似乎只能按列对值进行排名,而不是按行。
使用 numpy 的
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
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')
)
这可以通过 apply 和 lambda 函数的组合来完成(经过进一步调查):
df['rank1']=df.T.apply(lambda x: x.nlargest(1).idxmin())
df['rank2']=df.T.apply(lambda x: x.nlargest(2).idxmin())