对于我的单元测试,我想检查两个数组是否相同。简化示例:
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
. 最好的方法是什么?
对于我的单元测试,我想检查两个数组是否相同。简化示例:
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
. 最好的方法是什么?
对于 1.19 之前的 numpy 版本,这可能是不特别涉及单元测试的情况下的最佳方法:
>>> ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
True
但是,现代版本为该array_equal
函数提供了一个新的关键字参数 ,equal_nan
它完全符合要求。
这是flyingdutchman首先指出的;有关详细信息,请参阅下面的答案。
或者,您可以使用numpy.testing.assert_equal
或:numpy.testing.assert_array_equal
try/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
)可能更自然。
最简单的方法是使用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
会被打印出来。
您可以在此处找到相关文档
您可以使用 numpy 屏蔽数组,屏蔽NaN
值,然后使用numpy.ma.all
or 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
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
。不确定这是否是错误。
只是为了完成@Luis Albert Centeno 的回答,您可能宁愿使用:
np.allclose(a, b, rtol=0, atol=0, equal_nan=True)
rtol
并atol
控制等式检验的容差。简而言之,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
当我使用上述答案时:
((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
在评估字符串列表时,它给了我一些错误。
这是更通用的类型:
def EQUAL(a,b):
return ((a == b) | ((a != a) & (b != b)))
从v1.9 开始,numpy 的array_equal
函数支持一个equal_nan
参数:
assert np.array_equal(a, b, equal_nan=True)
对我来说,这很好用:
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 时忽略比较
如果您为单元测试之类的事情执行此操作,那么您不太关心所有类型的性能和“正确”行为,您可以使用它来获得适用于所有类型数组的东西,而不仅仅是数字:
a = np.array(['a', 'b', None])
b = np.array(['a', 'b', None])
assert list(a) == list(b)
将ndarray
s 强制转换为list
s有时对于在某些测试中获得您想要的行为很有用。(但不要在生产代码或更大的数组中使用它!)