我有各种各样的pandas数据帧,我想让它们对称。有时,行索引标签的数量将超过col标签,反之亦然。在任何一种情况下,结果数据帧的行和列标签都应该是所有标签的排序并集。任何缺失的数据都将填入np.nan
。
我的解决方案有效,但它涉及制作数据帧的3个副本:原始df,填充了col标签的df,以及填写了行标签的df。我尝试的任何其他解决方案都会导致不完全对称的矩阵。我正在寻求帮助,使我的解决方案更加简单,更加“pythonic”。
asym = pd.DataFrame.from_dict(
{'row': ['a','b','c','x','y','z','!'],
'a': [ n, -.8,-.6,-.3, .8, .01,n],
'b': [-.8, n, .5, .7,-.9, .01,n],
'c': [-.6, .5, n, .3, .1, .01,n],
'q': [-.3, .7, .3, n, .2, .01,n],
'r': [ .8,-.9, .1, .2, n, .01,n],
's': [ .01, .01, .01, .01, .01, n,n],
}).set_index('row')
不对称数据框:
请注意,列标签缺失"x","y","z","!"
且缺少行标签"q","r","s"
。
df = asym
c = df.columns
r = df.index
label_union = set(c).union(set(r))
# fill rows with unique labels
df_1 = df.reindex(index=label_union.difference(r).union(set(r)), fill_value=n)
# fill cols with unique labels
df_2 = df_1.reindex(columns=label_union.difference(c).union(set(c)), fill_value=n)
# sort labels
df_2.sort_index(axis=0, inplace=True)
df_2.sort_index(axis=1, inplace=True)
下面的结果是正确的,但制作三张df副本似乎是unpythonic。我还想执行上面的代码" inplace",因为我使用的数据帧很大且很多。帮我找到一个解决方案,在没有所有df副本的情况下给出正确的结果。
对称数据框:
关于使用"对称"的注意事项: 由此产生的数据帧不是严格对称的,这意味着该矩阵不等于其转置。我正在使用"对称"专门指代行和列标签。该玩具示例的矩阵模拟遗传交互矩阵,其中行和列是基因,并且相应的值是描绘该交互的分数。为了真正对称,矩阵意味着传递性,这在遗传相互作用中通常不是这样。
答案 0 :(得分:3)
您可以使用reindex
:
label_union = asym.index.union(asym.columns)
asym = asym.reindex(index=label_union, columns=label_union)
结果输出:
! a b c q r s x y z
! NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
a NaN NaN -0.80 -0.60 -0.30 0.80 0.01 NaN NaN NaN
b NaN -0.80 NaN 0.50 0.70 -0.90 0.01 NaN NaN NaN
c NaN -0.60 0.50 NaN 0.30 0.10 0.01 NaN NaN NaN
q NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
r NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
s NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
x NaN -0.30 0.70 0.30 NaN 0.20 0.01 NaN NaN NaN
y NaN 0.80 -0.90 0.10 0.20 NaN 0.01 NaN NaN NaN
z NaN 0.01 0.01 0.01 0.01 0.01 NaN NaN NaN NaN
答案 1 :(得分:2)
以下是使用np.ix_
的NumPy方法,可以简化2D
有效索引网格的创建,其余只是使用NaNs
初始化并分配 -
c = df.columns
r = df.index
L = np.union1d(c,r)
cols = np.searchsorted( L, c)
rows = np.searchsorted( L, r)
out = np.full((len(L),len(L)), np.nan)
out[np.ix_(rows, cols)] = df.values
df_out = pd.DataFrame(out, columns=L, index=L)
就内存要求而言,out
将是输出数据帧的视图,因此不会占用任何额外的内存。
示例输出 -
In [556]: df_out
Out[556]:
! a b c q r s x y z
! NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
a NaN NaN -0.80 -0.60 -0.30 0.80 0.01 NaN NaN NaN
b NaN -0.80 NaN 0.50 0.70 -0.90 0.01 NaN NaN NaN
c NaN -0.60 0.50 NaN 0.30 0.10 0.01 NaN NaN NaN
q NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
r NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
s NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
x NaN -0.30 0.70 0.30 NaN 0.20 0.01 NaN NaN NaN
y NaN 0.80 -0.90 0.10 0.20 NaN 0.01 NaN NaN NaN
z NaN 0.01 0.01 0.01 0.01 0.01 NaN NaN NaN NaN
答案 2 :(得分:1)
像今天一样获取两个索引的并集,然后使用2个链接的转置将数据帧重新索引两倍:
full_idx = asym.index.union(asym.columns)
asym.reindex(full_idx).T.reindex(full_idx).T
Out[116]:
! a b c q r s x y z
! NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
a NaN NaN -0.80 -0.60 -0.30 0.80 0.01 NaN NaN NaN
b NaN -0.80 NaN 0.50 0.70 -0.90 0.01 NaN NaN NaN
c NaN -0.60 0.50 NaN 0.30 0.10 0.01 NaN NaN NaN
q NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
r NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
s NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
x NaN -0.30 0.70 0.30 NaN 0.20 0.01 NaN NaN NaN
y NaN 0.80 -0.90 0.10 0.20 NaN 0.01 NaN NaN NaN
z NaN 0.01 0.01 0.01 0.01 0.01 NaN NaN NaN NaN