numpy 中 'invalid value encountered in less_equal' 的原因可能是什么

What might be the cause of 'invalid value encountered in less_equal' in numpy

我遇到了 RuntimeWarning

 RuntimeWarning: invalid value encountered in less_equal

由我的这行代码生成:

center_dists[j] <= center_dists[i]

center_dists[j]center_dists[i]都是numpy数组

出现此警告的原因可能是什么?

这很可能是因为所涉及的输入中某处存在 np.nan。它的一个例子如下所示-

In [1]: A = np.array([4, 2, 1])

In [2]: B = np.array([2, 2, np.nan])

In [3]: A<=B
RuntimeWarning: invalid value encountered in less_equal
Out[3]: array([False,  True, False], dtype=bool)

对于所有涉及 np.nan 的比较,它会输出 False。让我们确认一下以进行 broadcasted 比较。这是一个示例 -

In [1]: A = np.array([4, 2, 1])

In [2]: B = np.array([2, 2, np.nan])

In [3]: A[:,None] <= B
RuntimeWarning: invalid value encountered in less_equal
Out[3]: 
array([[False, False, False],
       [ True,  True, False],
       [ True,  True, False]], dtype=bool)

请注意输出中的第三列,它对应于涉及 B 中的第三个元素 np.nan 的比较,结果是所有 False 个值。

作为 Divakar 的回答及其关于如何抑制 RuntimeWarning 的评论的后续行动,更安全的方法是使用 [=12= 仅在 本地 抑制它们] (docs):当比较 np.nan 产生 False 时,通常会收到警告是很好的,只有当这确实是预期的时候才忽略警告。这里以 OP 为例:

with np.errstate(invalid='ignore'):
  center_dists[j] <= center_dists[i]

退出 with 块后,错误处理将重置为之前的状态。

而不是 invalid value encountered,也可以通过传递 all='ignore' 来忽略所有错误。有趣的是,np.errstate() 文档中的 kwargs 中没有,但 np.seterr() 文档中没有。 (似乎是 np.errstate() 文档中的一个小错误。)

这是由于数据帧中的 Nan 值造成的,这对于 DF 完全没问题。

在 Pycharm 中,这对我来说就像一个魅力:

import warnings

warnings.simplefilter(action = "ignore", category = RuntimeWarning)

Numpy 数据类型非常严格。所以它不会产生像 np.array([False, True, np.nan]) 这样的数组,而是 returns array([ 0., 1., nan])float 数组。

如果您尝试更改布尔数组,例如:

x= np.array([False, False, False])
x[0] = 5

将重新运行 array([ True, False, False]) ...哇

但是我觉得5>np.nan不可能是False,应该是nanFalse就说明做了数据比较,返回的结果是这样的3>5,我认为这是一场灾难。 Numpy 产生我们实际上没有的数据。如果它可以返回 nan 那么我们就可以轻松处理它。

所以我尝试用函数修改行为。

def ngrater(x, y):
    with np.errstate(invalid='ignore'):
        c=x>y
        c=c.astype(np.object)
        c[np.isnan(x)] = np.nan
        c[np.isnan(y)] = np.nan
        return c
a = np.array([np.nan,1,2,3,4,5, np.nan, np.nan, np.nan]) #9 elements
b = np.array([0,1,-2,-3,-4,-5, -5, -5, -5]) #9 elements

ngrater(a,b)

returns: array([nan, False, True, True, True, True, nan, nan, nan], dtype=object)

但我认为整个内存结构都以这种方式改变了。它不会获得具有统一单元的内存块,而是会生成一个指针块,其中真正的数据位于其他地方。所以功能可能会执行得更慢,这可能就是 Numpy 不这样做的原因。我们需要一个 superBool dtype,它也将包含 np.nan,或者我们只需要使用 float 数组 +1:True, -1:False, nan:nan

将上述答案添加到另一种抑制此警告的方法是 to use numpy.less explicitly,提供 whereout 参数:

np.less([1, 2], [2, np.nan])  

输出:array([ True, False]) 导致运行时警告,

np.less([1, 2], [2, np.nan], where=np.isnan([2, np.nan])==False)

不计算第二个数组元素 according to the docs 的结果,留下未定义的值(我得到了两个元素的 True 输出),而

np.less([1, 2], [2, np.nan], where=np.isnan([2, np.nan])==False, out=np.full((1, 2), False)

将结果写入预先初始化为 False 的数组(因此总是在第二个元素中给出 False)。