【发布时间】:2018-07-15 14:32:27
【问题描述】:
数据
我有一个数据框,其中包含给定 ID 的排名分数:
>>> ranks
ID rank
0 A 6
1 B 9
2 C 6
3 D 1
4 E 1
5 F 2
我想把它变成一个方阵,每个 ID 既作为索引又作为列,基于几个条件:如果索引上的 ID 排名高于 ID 在索引中的排名列,设置为1,如果小于,设置为0,如果相等,设置为0.5,如果索引与列相同,设置为np.nan。通过查看我想要的矩阵可以更好地描述这一点:
期望的结果
>>> mtrx
A B C D E F
A NaN 1.0 0.5 0.0 0.0 0.0
B 0.0 NaN 0.0 0.0 0.0 0.0
C 0.5 1.0 NaN 0.0 0.0 0.0
D 1.0 1.0 1.0 NaN 0.5 1.0
E 1.0 1.0 1.0 0.5 NaN 1.0
F 1.0 1.0 1.0 0.0 0.0 NaN
我所做的(有效,但速度很慢)
以下循环有效,但对于较大的数据帧,它很慢。如果有人可以为我指明一个更好的、更 Pythonic/pandorable 的方式来实现这一点,我希望得到一些帮助:
# Make an empty matrix as a dataframe
mtrx = pd.DataFrame(np.zeros((len(IDs), len(IDs))), index=IDs, columns = IDs)
# Populate it via for loop
for i in IDs:
for j in IDs:
i_rank = ranks.loc[ranks['ID'] == i].iloc[0]['rank']
j_rank = ranks.loc[ranks['ID'] == j].iloc[0]['rank']
if i == j:
mtrx.loc[i, j] = np.nan
elif i_rank < j_rank:
mtrx.loc[i, j] = 1.
elif i_rank == j_rank:
mtrx.loc[i, j] = 0.5
重现此玩具示例的代码
import pandas as pd
import numpy as np
np.random.seed(1)
IDs = list('ABCDEF')
ranks = pd.DataFrame({'ID':IDs, 'rank':np.random.randint(1,10,len(IDs))})
【问题讨论】: