使用numpy

时间:2016-11-07 19:58:00

标签: numpy nan

我有一个带NaN的数组,比如说

>>> a = np.random.randn(3, 3)
>>> a[1, 1] = a[2, 2] = np.nan
>>> a
array([[-1.68425874,  0.65435007,  0.55068277],
       [ 0.71726307,         nan, -0.09614409],
       [-1.45679335, -0.12772348,         nan]])

我想将此数组中的负数设置为-1。这样做“直截了当”会导致警告,我试图避免:

>>> a[a < 0] = -1
__main__:1: RuntimeWarning: invalid value encountered in less
>>> a
array([[-1.        ,  0.65435007,  0.55068277],
       [ 0.71726307,         nan, -1.        ],
       [-1.        , -1.        ,         nan]])

对掩码应用AND会产生相同的警告,因为当然a < 0被计算为一个单独的临时数组:

>>> n = ~np.isnan(a)
>>> a[n & (a < 0)] = -1
__main__:1: RuntimeWarning: invalid value encountered in less

当我尝试在a之外应用掩码时,掩码部分不会写回原始数组:

>>> n = ~np.isnan(a)
>>> a[n][a[n] < 0] = -1
>>> a
array([[-1.68425874,  0.65435007,  0.55068277],
       [ 0.71726307,         nan, -0.09614409],
       [-1.45679335, -0.12772348,         nan]])

我能解决这个问题的唯一方法是使用免费的a中间掩码版本:

>>> n = ~np.isnan(a)
>>> b = a[n]
>>> b[b < 0] = -1
>>> a[n] = b
>>> a
array([[-1.        ,  0.65435007,  0.55068277],
       [ 0.71726307,         nan, -1.        ],
       [-1.        , -1.        ,         nan]])

是否有更简单的方法在存在NaN的情况下执行此屏蔽分配?如果可能的话,我想在不使用掩码数组的情况下解决这个问题。

注意

上面的代码段最好用

运行
import numpy as np
import warnings
np.seterr(all='warn')
warnings.simplefilter("always")

根据https://stackoverflow.com/a/30496556/2988730

3 个答案:

答案 0 :(得分:2)

如果您想避免在包含a < 0的{​​{1}}的{​​{1}}发生此警告,我认为使用aNaNs索引会有其他方法flattened个职位然后进行比较。因此,我们将采用两种方法来实现这一理念。

具有扁平指数的一个 -

row-column

另一个下标索引 -

non-Nan

答案 1 :(得分:2)

您可以暂时取消警告,这是您所追求的吗?

In [9]: a = np.random.randn(3, 3)

In [10]: a[1, 1] = a[2, 2] = np.nan

In [11]: with np.errstate(invalid='ignore'):
   ....:     a[a < 0] = -1
   ....:

答案 2 :(得分:1)

找到我发现的np.nan...

np.nan_to_num个函数
In [569]: a=np.arange(9.).reshape(3,3)-5
In [570]: a[[1,2],[1,2]]=np.nan
In [571]: a
Out[571]: 
array([[ -5.,  -4.,  -3.],
       [ -2.,  nan,   0.],
       [  1.,   2.,  nan]])
In [572]: np.nan_to_num(a)   # replace nan with 0
Out[572]: 
array([[-5., -4., -3.],
       [-2.,  0.,  0.],
       [ 1.,  2.,  0.]])
In [573]: np.nan_to_num(a)<0    # and safely do the <
Out[573]: 
array([[ True,  True,  True],
       [ True, False, False],
       [False, False, False]], dtype=bool)
In [574]: a[np.nan_to_num(a)<0]=-1
In [575]: a
Out[575]: 
array([[ -1.,  -1.,  -1.],
       [ -1.,  nan,   0.],
       [  1.,   2.,  nan]])

查看nan_to_num代码,看起来它使用了屏蔽的copyto

In [577]: a1=a.copy(); np.copyto(a1, 0.0, where=np.isnan(a1))
In [578]: a1
Out[578]: 
array([[-1., -1., -1.],
       [-1.,  0.,  0.],
       [ 1.,  2.,  0.]])

所以它就像你的版本中的“无偿”版本一样。掩码,但它隐藏在函数中。

np.placenp.putmask是使用掩码的其他函数。