85

对于我的单元测试,我想检查两个数组是否相同。简化示例:

a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])

if np.all(a==b):
    print 'arrays are equal'

这不起作用,因为nan != nan. 最好的方法是什么?

4

10 回答 10

50

对于 1.19 之前的 numpy 版本,这可能是不特别涉及单元测试的情况下的最佳方法:

>>> ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
True

但是,现代版本为该array_equal函数提供了一个新的关键字参数 ,equal_nan它完全符合要求。

这是flyingdutchman首先指出的;有关详细信息,请参阅下面的答案

于 2012-05-22T21:24:50.127 回答
47

或者,您可以使用numpy.testing.assert_equal或:numpy.testing.assert_array_equaltry/except

In : import numpy as np

In : def nan_equal(a,b):
...:     try:
...:         np.testing.assert_equal(a,b)
...:     except AssertionError:
...:         return False
...:     return True

In : a=np.array([1, 2, np.NaN])

In : b=np.array([1, 2, np.NaN])

In : nan_equal(a,b)
Out: True

In : a=np.array([1, 2, np.NaN])

In : b=np.array([3, 2, np.NaN])

In : nan_equal(a,b)
Out: False

编辑

由于您将其用于单元测试,因此 bare assert(而不是将其包装为 get True/False)可能更自然。

于 2012-05-22T21:42:36.257 回答
43

最简单的方法是使用numpy.allclose()方法,它允许指定具有 nan 值时的行为。然后您的示例将如下所示:

a = np.array([1, 2, np.nan])
b = np.array([1, 2, np.nan])

if np.allclose(a, b, equal_nan=True):
    print('arrays are equal')

然后arrays are equal会被打印出来。

您可以在此处找到相关文档

于 2017-08-14T13:05:21.487 回答
9

您可以使用 numpy 屏蔽数组,屏蔽NaN值,然后使用numpy.ma.allor numpy.ma.allclose

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.all.html

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.allclose.html

例如:

a=np.array([1, 2, np.NaN])
b=np.array([1, 2, np.NaN])
np.ma.all(np.ma.masked_invalid(a) == np.ma.masked_invalid(b)) #True
于 2012-05-22T21:23:25.867 回答
8

numpy 函数array_equal完全符合问题的要求。当被问到时,它很可能不存在。该示例如下所示:

a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])
assert np.array_equal(a, b, equal_nan=True)

但是请注意,如果元素是 dtype ,这将不起作用object。不确定这是否是错误

于 2020-12-09T14:57:19.710 回答
8

只是为了完成@Luis Albert Centeno 的回答,您可能宁愿使用:

np.allclose(a, b, rtol=0, atol=0, equal_nan=True)

rtolatol控制等式检验的容差。简而言之,allclose()返回:

all(abs(a - b) <= atol + rtol * abs(b))

默认情况下,它们未设置为 0,因此True如果您的数字接近但不完全相等,该函数可能会返回。


PS:“我想检查两个数组是否相同”>>实际上,您正在寻找equal而不是identity。它们在 Python 中是不一样的,我认为每个人都最好了解它们的区别以便共享相同的词典。(https://www.blog.pythonlibrary.org/2017/02/28/python-101-equality-vs-identity/

您将通过关键字测试身份is

a is b
于 2019-11-05T10:13:57.273 回答
7

当我使用上述答案时:

 ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()

在评估字符串列表时,它给了我一些错误。

这是更通用的类型:

def EQUAL(a,b):
    return ((a == b) | ((a != a) & (b != b)))
于 2016-10-10T12:07:42.460 回答
1

v1.9 开始,numpy 的array_equal函数支持一个equal_nan参数:

assert np.array_equal(a, b, equal_nan=True)
于 2021-03-24T22:58:20.090 回答
0

对我来说,这很好用:

a = numpy.array(float('nan'), 1, 2)
b = numpy.array(2, float('nan'), 2)
numpy.equal(a, b, where = 
    numpy.logical_not(numpy.logical_or(
        numpy.isnan(a), 
        numpy.isnan(b)
    ))
).all()

PS。有 nan 时忽略比较

于 2021-05-02T22:47:08.570 回答
0

如果您为单元测试之类的事情执行此操作,那么您不太关心所有类型的性能和“正确”行为,您可以使用它来获得适用于所有类型数组的东西,而不仅仅是数字

a = np.array(['a', 'b', None])
b = np.array(['a', 'b', None])
assert list(a) == list(b)

ndarrays 强制转换为lists有时对于在某些测试中获得您想要的行为很有用。(但不要在生产代码或更大的数组中使用它!)

于 2019-01-16T23:08:38.707 回答