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

Posted

技术标签:

【中文标题】numpy 数组与 nan 与标量的不等式比较【英文标题】:inequality comparison of numpy array with nan to a scalar 【发布时间】:2014-10-10 08:03:27 【问题描述】:

我正在尝试将低于阈值的数组成员设置为 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 并且我不能引入新的依赖项。谢谢。

【问题讨论】:

【参考方案1】:

np.less() 有一个where 参数,用于控制将在何处应用操作。所以你可以这样做:

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

【讨论】:

你可以简单地使用where=np.isfinite(x)【参考方案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

【讨论】:

【参考方案3】:

我个人在已经给出的答案中忽略了使用 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 参数设置不正确的输出。

【讨论】:

请注意,out=mask 关键字参数是此工作所必需的。否则,np.less 将在跳过的位置返回 True【参考方案4】:

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

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

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

【讨论】:

谢谢。我认为在警告中使用警告过滤器可能有更安全的方法: warnings.filterwarnings("ignore") 然后是 这也是一个全局更改...如果立即重置,可以说是相当安全的。然而,正如我给 Jamie 的笔记所暗示的那样,我意识到了这种方法。我一直在寻找没有这种开销的东西。但是我认为您的回答可能对很多人有所帮助。 您可以使用errstate 作为偏好。【参考方案5】:

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

【讨论】:

我同意这个逻辑,我很高兴你指出这不是他通常的 nan-isn't-equal-to-nan 问题。当我尝试这样做时,我遇到的问题是它会产生运行时警告。一种选择是导入警告并捕获它,但这需要大量输入和开销。我希望有一个经济的替代方案。 有谁知道为什么np.nan 允许进行比较(总是评估为False 而不是引发TypeError 或None &lt; x 那样的东西)?如果一些 nans 从 numpy 数组中逃逸到常规 Python 变量中,并且您开始将它们与常规 Python 方法和表达式一起使用,则会引起各种头痛。 这就是 NaN 根据 IEEE 754 应该做的事情,你会得到相同的行为,例如来自float('nan'):en.wikipedia.org/wiki/NaN#Comparison_with_NaN

以上是关于numpy 数组与 nan 与标量的不等式比较的主要内容,如果未能解决你的问题,请参考以下文章

Python\Numpy:将数组与 NAN 进行比较 [重复]

如何对齐两个大小不等的时间序列numpy数组?

以大约相等的计算成本将不等大小的 pandas/numpy 数组分箱

Javascript 中 null,NaN和undefined的区别

set与map

js ==与===区别(两个等号与三个等号)