具有对称列和索引(行)标签的Pandas数据帧

时间:2017-01-30 21:47:06

标签: python pandas numpy set

问题陈述:

我有各种各样的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')

不对称数据框:

asymmetrical df

请注意,列标签缺失"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副本的情况下给出正确的结果。

对称数据框:

symmetrical df

关于使用"对称"的注意事项: 由此产生的数据帧不是严格对称的,这意味着该矩阵不等于其转置。我正在使用"对称"专门指代行和列标签。该玩具示例的矩阵模拟遗传交互矩阵,其中行和列是基因,并且相应的值是描绘该交互的分数。为了真正对称,矩阵意味着传递性,这在遗传相互作用中通常不是这样。

3 个答案:

答案 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