在 argsort 之后汇总每列的排名

Summarise ranks of each column after argsort

我有一个 df 有几个“属性”和每个属性的分数:

df = pd.DataFrame(np.random.random_sample((5, 3)), columns=['speed', 'endurance', 'strength'])


      speed     endurance   strength
0   0.901001    0.531624    0.599738
1   0.302515    0.439233    0.143280
2   0.616964    0.984054    0.151714
3   0.681594    0.601456    0.655960
4   0.831605    0.742175    0.276892

因此,对于每一行,我可以根据分数列出主要、次要和第三属性,df.to_numpy().argsort()

我需要得到每个属性达到每个位置的次数的摘要,例如:

position  speed endurance strength
primary        3    2   0
secondary      2    1   2
tertiary       0    2   3

(我是手工计算的,所以可能会有误差,但希望原理是清楚的。)

我想我可以通过 (np.argsort(arr)==0).sum() 为每个 [0, 1, 2] 做到这一点,但是有更简单的方法吗?

您可以计算从 argsort 创建的 DataFrame,并将缺失值替换为 0rename 索引值,并按 DataFrame.iloc 更改顺序或行:

d = {2:'primary',1:'secondary', 0:'tertiary'}
df = (pd.DataFrame(df.to_numpy().argsort(), columns=df.columns)
        .apply(pd.value_counts)
        .fillna(0)
        .astype(int)
        .iloc[::-1]
        .rename(d))

print (df)
           speed  endurance  strength
primary        3          2         0
secondary      2          1         2
tertiary       0          2         3

您可以使用 rank and crosstab:

# names
d = {1:'primary',2:'secondary', 3:'tertiary'}

# ranks
s = df.rank(1, ascending=False).stack().map(d)

out = pd.crosstab(s, s.index.get_level_values(1)).rename_axis(index=None, columns=None)

输出:

           endurance  speed  strength
primary            2      3         0
secondary          1      2         2
tertiary           2      0         3

替代格式:

out = (pd.crosstab(s, s.index.get_level_values(1))
         .rename_axis(index='position', columns=None).reset_index()
       )

输出:

    position  endurance  speed  strength
0    primary          2      3         0
1  secondary          1      2         2
2   tertiary          2      0         3