在 numpy 中存在 NaN 的掩码位置设置值
Setting a value in masked location with NaNs present in numpy
我有一个包含 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
。以 "straightforward" 方式执行此操作会导致出现警告,而我正试图避免这种情况:
>>> 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
中的 nans 应用掩码时,掩码部分未写回原始数组:
>>> 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")
根据 .
如果您想避免在 a < 0
处出现 a
包含 NaNs
的警告,我认为替代方法包括使用 flattened
或 row-column
non-Nan
个位置的索引,然后执行比较。因此,我们将有两种采用该理念的方法。
具有扁平索引的一个 -
idx = np.flatnonzero(~np.isnan(a))
a.ravel()[idx[a.ravel()[idx] < 0]] = -1
另一个 下标指数 -
r,c = np.nonzero(~np.isnan(a))
mask = a[r,c] < 0
a[r[mask],c[mask]] = -1
您可以暂时取消警告,这是您想要的吗?
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
....:
查看我发现的 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.]])
所以它就像你的带有 'gratuitous' 掩码的版本,但它隐藏在函数中。
np.place
、np.putmask
是其他使用掩码的函数。
我有一个包含 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
。以 "straightforward" 方式执行此操作会导致出现警告,而我正试图避免这种情况:
>>> 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
中的 nans 应用掩码时,掩码部分未写回原始数组:
>>> 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")
根据
如果您想避免在 a < 0
处出现 a
包含 NaNs
的警告,我认为替代方法包括使用 flattened
或 row-column
non-Nan
个位置的索引,然后执行比较。因此,我们将有两种采用该理念的方法。
具有扁平索引的一个 -
idx = np.flatnonzero(~np.isnan(a))
a.ravel()[idx[a.ravel()[idx] < 0]] = -1
另一个 下标指数 -
r,c = np.nonzero(~np.isnan(a))
mask = a[r,c] < 0
a[r[mask],c[mask]] = -1
您可以暂时取消警告,这是您想要的吗?
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
....:
查看我发现的 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.]])
所以它就像你的带有 'gratuitous' 掩码的版本,但它隐藏在函数中。
np.place
、np.putmask
是其他使用掩码的函数。