将pandas DataFrame中的对角线三角形设置为NaN

时间:2016-11-19 08:39:28

标签: python pandas numpy

鉴于以下数据框:

import pandas as pd
import numpy as np
a = np.arange(16).reshape(4, 4)
df = pd.DataFrame(data=a, columns=['a','b','c','d'])

我想产生以下结果:

df([[ NaN,  1,  2,  3],
    [ NaN,  NaN,  6,  7],
    [ NaN,  NaN,  NaN, 11],
    [ NaN,  NaN,  NaN,  NaN]])

到目前为止,我已尝试使用np.tril_indicies,但它仅适用于将df转换为numpy数组,并且仅适用于整数赋值(不是np.nan):

il1 = np.tril_indices(4)
a[il1] = 0

给出:

array([[ 0,  1,  2,  3],
       [ 0,  0,  6,  7],
       [ 0,  0,  0, 11],
       [ 0,  0,  0,  0]])

......这几乎是我正在寻找的东西,但在分配NaN的时候是barf:

ValueError: cannot convert float NaN to integer

,同时:

df[il1] = 0

给出:

TypeError: unhashable type: 'numpy.ndarray'

因此,如果我想用NaN填充数据帧的底部三角形,它是否必须是一个numpy数组,或者我可以直接使用pandas吗? 2)有没有办法用NaN填充底部三角形而不是使用numpy.fill_diagonal并在整个DataFrame中逐行递增偏移量?

另一个失败的解决方案: 用零填充np数组的对角线,然后屏蔽零并重新分配给np.nan。当它们应保留为零时,它将对角线上方的零值转换为NaN!

2 个答案:

答案 0 :(得分:4)

您需要投放到float a,因为type的{​​{1}}为NaN

float

答案 1 :(得分:4)

使用np.where -

的方法
m,n = df.shape
df[:] = np.where(np.arange(m)[:,None] >= np.arange(n),np.nan,df)

示例运行 -

In [93]: df
Out[93]: 
    a   b   c   d
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15

In [94]: m,n = df.shape

In [95]: df[:] = np.where(np.arange(m)[:,None] >= np.arange(n),np.nan,df)

In [96]: df
Out[96]: 
    a    b    c     d
0 NaN  1.0  2.0   3.0
1 NaN  NaN  6.0   7.0
2 NaN  NaN  NaN  11.0
3 NaN  NaN  NaN   NaN