【问题标题】:inequality comparison of numpy array with nan to a scalarnumpy 数组与 nan 与标量的不等式比较
【发布时间】: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 并且我不能引入新的依赖项。谢谢。

【问题讨论】:

    标签: python numpy indexing nan inequality


    【解决方案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
      猜你喜欢
      • 2012-06-04
      • 2014-07-11
      • 1970-01-01
      • 2019-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-20
      相关资源
      最近更新 更多