21

我正在尝试将低于阈值的数组成员设置为 nan。这是 QA/QC 流程的一部分,传入的数据可能已经有 nan 的插槽。

例如,我的阈值可能是 -1000,因此我想在以下数组中将 -3000 设置为 nan

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

以下是:

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

会产生正确的行为,但也会产生 RuntimeWarning,但会产生禁用警告的开销

warnings.filterwarnings("ignore")
...
warnints.resetwarnings()

有点重,可能有点不安全。

尝试使用以下精美索引进行两次索引不会产生任何效果:

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

我认为这是因为整数索引或使用两次索引而制作了副本。

有没有人有一个相对简单的解决方案?在过程中使用掩码数组会很好,但最终产品必须是 ndarray 并且我不能引入新的依赖项。谢谢。

4

5 回答 5

18

一种选择是禁用相关警告numpy.errstate

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

要全局关闭相关警告,请使用numpy.seterr.

于 2014-08-18T00:21:20.190 回答
15

!=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
于 2014-08-17T06:58:09.573 回答
8

np.less()有一个where参数来控制操作的应用位置。所以你可以这样做:

x[np.less(x, -1000., where=~np.isnan(x))] = np.nan
于 2019-02-07T18:20:58.273 回答
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
于 2018-09-12T00:31:40.123 回答
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 ufunc采用可选参数where,并且仅在为真时对其进行评估,这与np.where评估两个选项然后选择相关选项的函数不同。out然后,当它不正确时,您可以使用参数设置所需的输出。

于 2017-11-01T20:51:29.667 回答