numpy数组与标量的nan不等比较

21 投票
5 回答
18174 浏览
提问于 2025-04-18 17:32
warnings.filterwarnings("ignore")
...
warnints.resetwarnings()

我想把一个数组中低于某个阈值的元素设置为nan。这是质量检查过程的一部分,因为输入的数据可能已经有一些位置是nan。

举个例子,我的阈值可能是-1000,所以我想把数组中的-3000设置为nan。

x = np.array([np.nan,1.,2.,-3000.,np.nan,5.])

下面这段代码:

x[x < -1000.] = np.nan

能正确运行,但会产生一个运行时警告,而关闭这个警告的开销有点大,而且可能不太安全。

尝试用复杂的索引方式两次索引,如下所示,并没有产生任何效果:

nonan = np.where(~np.isnan(x))[0]
x[nonan][x[nonan] < -1000.] = np.nan

我猜这是因为使用整数索引或两次索引时会生成一个副本。

有没有人能提供一个相对简单的解决方案?使用掩码数组也可以,但最终的结果必须是ndarray,并且我不能引入新的依赖。谢谢。

5 个回答

2

虽然有点晚了,但我会这样做:

x = np.array([np.nan,1.,2.,-3000.,np.nan,5.]) 

igood=np.where(~np.isnan(x))[0]
x[igood[x[igood]<-1000.]]=np.nan
2

我个人在使用之前提到的np.errstate上下文管理器时,会忽略警告,因为代码的清晰度比花额外时间更重要,但这里有一个替代方案。

# given
x = np.array([np.nan, 1., 2., -3000., np.nan, 5.])

# apply NaNs as desired
mask = np.zeros(x.shape, dtype=bool)
np.less(x, -1000, out=mask, where=~np.isnan(x))
x[mask] = np.nan

# expected output and comparison
y = np.array([np.nan, 1., 2., np.nan, np.nan, 5.])
assert np.allclose(x, y, rtol=0., atol=1e-14, equal_nan=True)

numpy中的less这个函数有一个可选的参数where,它只在条件为真的时候进行计算,这和np.where函数不同,后者会计算两个选项,然后选择一个相关的结果。你可以通过out参数来设置在条件不成立时的期望输出。

9

np.less() 这个函数有一个叫做 where 的参数,它可以控制这个操作将在哪些地方进行。所以你可以这样做:

x[np.less(x, -1000., where=~np.isnan(x))] = np.nan
18

一种选择是使用 numpy.errstate 来关闭相关的警告:

with numpy.errstate(invalid='ignore'):
    ...

如果你想全局关闭这些警告,可以使用 numpy.seterr

17

任何将NaN(不是一个数字)与非NaN值进行比较(除了!=)的操作,结果总是会返回False,也就是说它们永远不会相等:

>>> x < -1000
array([False, False, False,  True, False, False], dtype=bool)

所以你可以简单地忽略数组中已经存在的NaN,直接这样做:

>>> x[x < -1000] = np.nan
>>> x
array([ nan,   1.,   2.,  nan,  nan,   5.])

编辑 我在运行上面的代码时没有看到任何警告,但如果你真的想避免NaN,可以尝试这样做:

mask = ~np.isnan(x)
mask[mask] &= x[mask] < -1000
x[mask] = np.nan

撰写回答