NPE*_*NPE 21 python comparison numpy nan
是否有一种惯用的方法来比较两个NumPy数组,这些数组会将NaN视为彼此相等(但不等于NaN以外的任何其他数据).
例如,我希望以下两个数组比较相等:
np.array([1.0, np.NAN, 2.0])
np.array([1.0, np.NAN, 2.0])
Run Code Online (Sandbox Code Playgroud)
和以下两个数组进行比较不相等:
np.array([1.0, np.NAN, 2.0])
np.array([1.0, 0.0, 2.0])
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种可以产生标量布尔结果的方法.
以下是这样做的:
np.all((a == b) | (np.isnan(a) & np.isnan(b)))
Run Code Online (Sandbox Code Playgroud)
但它很笨重,并创建所有这些中间阵列.
有没有一种方法更容易在眼睛上更好地利用记忆?
PS如果有帮助,已知阵列具有相同的形状和dtype.
seg*_*sai 16
如果你真的关心内存使用(例如有非常大的数组),那么你应该使用numexpr,下面的表达式将适合你:
np.all(numexpr.evaluate('(a==b)|((a!=a)&(b!=b))'))
Run Code Online (Sandbox Code Playgroud)
我已经在长度为3e8的非常大的数组上测试了它,并且代码在我的机器上具有相同的性能
np.all(a==b)
Run Code Online (Sandbox Code Playgroud)
并使用相同数量的内存
Numpy 1.10将equal_nan关键字添加到np.allclose(https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html).
所以你现在可以做到:
In [24]: np.allclose(np.array([1.0, np.NAN, 2.0]),
np.array([1.0, np.NAN, 2.0]), equal_nan=True)
Out[24]: True
Run Code Online (Sandbox Code Playgroud)
免责声明:我不建议将其用于常规使用,我不会自己使用它,但我可以想象它可能有用的罕见情况.
如果数组具有相同的形状和dtype,您可以考虑使用低级memoryview:
>>> import numpy as np
>>>
>>> a0 = np.array([1.0, np.NAN, 2.0])
>>> ac = a0 * (1+0j)
>>> b0 = np.array([1.0, np.NAN, 2.0])
>>> b1 = np.array([1.0, np.NAN, 2.0, np.NAN])
>>> c0 = np.array([1.0, 0.0, 2.0])
>>>
>>> memoryview(a0)
<memory at 0x85ba1bc>
>>> memoryview(a0) == memoryview(a0)
True
>>> memoryview(a0) == memoryview(ac) # equal but different dtype
False
>>> memoryview(a0) == memoryview(b0) # hooray!
True
>>> memoryview(a0) == memoryview(b1)
False
>>> memoryview(a0) == memoryview(c0)
False
Run Code Online (Sandbox Code Playgroud)
但要注意像这样的微妙问题:
>>> zp = np.array([0.0])
>>> zm = -1*zp
>>> zp
array([ 0.])
>>> zm
array([-0.])
>>> zp == zm
array([ True], dtype=bool)
>>> memoryview(zp) == memoryview(zm)
False
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为二进制表示形式不同,即使它们比较相等(当然,它们必须知道如何打印负号)
>>> memoryview(zp)[0]
'\x00\x00\x00\x00\x00\x00\x00\x00'
>>> memoryview(zm)[0]
'\x00\x00\x00\x00\x00\x00\x00\x80'
Run Code Online (Sandbox Code Playgroud)
从好的方面来说,它会让你希望的方式缩短:
In [47]: a0 = np.arange(10**7)*1.0
In [48]: a0[-1] = np.NAN
In [49]: b0 = np.arange(10**7)*1.0
In [50]: b0[-1] = np.NAN
In [51]: timeit memoryview(a0) == memoryview(b0)
10 loops, best of 3: 31.7 ms per loop
In [52]: c0 = np.arange(10**7)*1.0
In [53]: c0[0] = np.NAN
In [54]: d0 = np.arange(10**7)*1.0
In [55]: d0[0] = 0.0
In [56]: timeit memoryview(c0) == memoryview(d0)
100000 loops, best of 3: 2.51 us per loop
Run Code Online (Sandbox Code Playgroud)
并进行比较:
In [57]: timeit np.all((a0 == b0) | (np.isnan(a0) & np.isnan(b0)))
1 loops, best of 3: 296 ms per loop
In [58]: timeit np.all((c0 == d0) | (np.isnan(c0) & np.isnan(d0)))
1 loops, best of 3: 284 ms per loop
Run Code Online (Sandbox Code Playgroud)