Python\Numpy: 比较包含NAN的数组
为什么下面这两个列表不相等呢?
a = [1.0, np.NAN]
b = np.append(np.array(1.0), [np.NAN]).tolist()
我用以下方法来检查它们是否相同。
((a == b) | (np.isnan(a) & np.isnan(b))).all(), np.in1d(a,b)
使用 np.in1d(a, b)
这个方法时,发现 np.NAN
的值不相等,但我不太明白这是为什么。有没有人能帮我解释一下这个问题?
3 个回答
0
在Python(还有numpy库)中,NaN是按照IEEE 754标准来实现的(你可以查看这个链接了解更多:http://en.wikipedia.org/wiki/NaN)。简单来说,NaN被定义为“无法排序的”。这意味着在比较操作中,比如用<
、>
、==
等来判断时,NaN永远不会返回True。为了判断一个值是否是NaN,numpy和内置的math
模块提供了isnan
这个函数。
8
NaN
值是“不是一个数字”的意思,它们永远不会被认为是相等的。也就是说,测试 NaN==NaN
的结果总是 False
,这是因为 NaN
的定义就是这样。
所以 [1.0, NaN] == [1.0, NaN]
的结果也是 False
。实际上,一旦在任何列表中出现了 NaN
,它就无法与任何其他列表进行相等比较,甚至连它自己也不行。
如果你想检查一个变量是否是 NaN
,可以在 numpy
中使用 numpy.isnan()
这个函数。我没有看到有什么简单的方法可以实现你想要的比较,除了通过“手动”使用循环来遍历列表。
考虑以下代码:
import math
import numpy as np
def nan_eq(a, b):
for i,j in zip(a,b):
if i!=j and not (math.isnan(i) and math.isnan(j)):
return False
return True
a=[1.0, float('nan')]
b=[1.0, float('nan')]
print( float('nan')==float('nan') )
print( a==a )
print( a==b )
print( nan_eq(a,a) )
这段代码会打印:
False
True
False
True
测试 a==a
成功是因为,Python认为对同一个对象的引用是相等的,这种想法优先于 a==b
所需的逐元素比较的结果。
5
因为 a
和 b
是列表,所以 a == b
不会返回一个数组,所以你用的那种类似于numpy的逻辑是行不通的:
>>> a == b
False
你提到的这个命令只有在它们是 数组 的时候才有效:
>>> a,b = np.asarray(a), np.asarray(b)
>>> a == b
array([ True, False], dtype=bool)
>>> (a == b) | (np.isnan(a) & np.isnan(b))
array([ True, True], dtype=bool)
>>> ((a == b) | (np.isnan(a) & np.isnan(b))).all()
True
这个命令应该可以用来比较两个数组(要么它们相等,要么它们都是NaN)。