我有以下形式的矩阵(不一定是正方形):
A B C D
A 0 0.2 0.3 0.5
E 0.2 0.6 0.9 0.2
D 0.5 0.3 0.6 0
F 0.1 0.4 0.5 0.3
我想将其转换为方阵,如下所示
A B C D E F
A 0 0.2 0.3 0.5 0.2 0.1
B 0.2 0 0 0.3 0.6 0.4
C 0.3 0 0 0.6 0.9 0.5
D 0.5 0.3 0.6 0 0.2 0.3
E 0.2 0.6 0.9 0.2 0 0
F 0.1 0.4 0.5 0.3 0 0
换句话说,我想同时扩展行和列,以便它是一个对称的方矩阵(行和列的顺序相同),缺失的值填充为0。
我猜想应该有一种方法可以使用熊猫的内置函数轻松/有效地做到这一点,但我对该软件包并不熟悉。
为方便起见:
df = pd.DataFrame([[0, 0.2, 0.3, 0.5],
[0.2, 0.6, 0.9, 0.2],
[0.5, 0.3, 0.6, 0],
[0.1, 0.4, 0.5, 0.3]],
index=['A', 'E', 'D', 'F'],
columns=['A', 'B', 'C', 'D'])
答案 0 :(得分:2)
就像您认为的那样,您绝对可以在Pandas中简洁地做到这一点。
一种方法是使用非常好的combine_first方法。
result = df.combine_first(df.T).fillna(0.0)
但是,在我使用timeit进行的测试中,每个循环的时钟频率为3.62 ms±29.2 µs,实际上比我为your method获得的时间稍慢(每个循环3.5 ms±28.6 µs)
但是,通过使用update方法在Pandas中更直接地进行计算,我能够将其降低到2.04 ms±17.2 µs /每环µs /环(〜1.7倍的速度)。
# Find the combination of both indices
full_index = df.index.union(df.columns)
# Resize the DataFrame to include all the rows and columns
all_data = df.reindex(labels=full_index, axis=0).reindex(labels=full_index, axis=1)
# Update any values we have from the transpose
all_data.update(all_data.T)
# Fill the missing entries
result = all_data.fillna(0.0)
老实说,我无法获得我认为可以得到的最大性能提升,但是至少两个基于熊猫的版本对我而言至少更具可读性。
答案 1 :(得分:1)
# create three groups
common = set.intersection(set(df.columns.values), set(df.index))
missing_row = set(df.index) - common
missing_col = set(df.columns.values) - common
# put groups in order (might not be necessary)
ordered = list(common)+list(missing_col)+list(missing_row)
def symmetrize(a):
return a + a.T
# take the common part and extend it to order
common_part = df.loc[common, common]
common_part = common_part.reindex(index=ordered, columns=ordered, fill_value=0)
# take the remaining part
to_add = df.copy().reindex(index=ordered, columns=ordered, fill_value=0) - common_part
# make sure its symmetric, we can do a+a.T because here every value is only written once and its symmetric position is 0
to_add = symmetrize(to_add.values)
# convert to final form
common_part = common_part+common_part.T
result = pd.DataFrame(common_part + to_add, columns=ordered, index=ordered)
result = result[[*ordered]]
result = result.reindex(ordered)