空记录数组的单元测试相等性
Unittest equality of empty record arrays
我注意到以下 unittest.TestCase 断言失败了,我想知道如何正确比较空的 recarrays:
失败:
self.assertEqual(
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)
通过:
self.assertEqual(
np.array(
[(1,1)],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[(1,1)],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)
这是一个错误还是我做错了什么?
我只能假设 unittest.TestCase.assertEqual
使用 __eq__
方法,该方法在 numpy.ndarray
对象中 elementwise 相等。因此,在两个空数组上使用 ==
returns 一个空布尔数组,即 falsy:
>>> arr1
rec.array([],
dtype=[('time', '<M8[ns]'), ('end_time', '<i8')])
>>> arr2
rec.array([],
dtype=[('time', '<M8[ns]'), ('end_time', '<i8')])
>>> bool(arr1 == arr2)
False
现在,在您的第二种情况下,您正在处理另一种特殊情况,即形状为 (1,)
的数组,这是具有单个元素的两个记录数组的元素相等的结果。本质上,对于具有单个项目的数组,真实性是元素的真实性:
>>> bool(np.array([1]))
True
>>> bool(np.array([0]))
False
>>> bool(np.array([{}]))
False
>>> bool(np.array([{'a':1}]))
True
>>> bool(np.array([object()]))
True
因此,使用您的数组:
>>> arr3 = np.array(
... [(1,1)],
... dtype=[
... ('time', 'datetime64[ns]'),
... ('end_time', int)
... ]
... ).view(np.recarray)
>>> arr4 = np.array(
... [(1,1)],
... dtype=[
... ('time', 'datetime64[ns]'),
... ('end_time', int)
... ]
... ).view(np.recarray)
>>> arr3.size, arr4.size
(1, 1)
>>> arr3 == arr4
rec.array([ True],
dtype=bool)
>>> bool(arr3 == arr4)
True
请注意,在任何情况下,如果结果数组的 .size
大于 1,那么如果您尝试计算真值,就会出现这个臭名昭著的错误,因此:
>>> np.array([1, 1]) == np.array([1, 1])
array([ True, True], dtype=bool)
>>> bool(np.array([1, 1]) == np.array([1, 1]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>>
@juanpa.arrivillaga 是正确的。但除此之外,您应该注意,最好使用 numpy.testing
模块对 NumPy 数组进行测试。例如:
np.testing.assert_equal(
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)
我注意到以下 unittest.TestCase 断言失败了,我想知道如何正确比较空的 recarrays:
失败:
self.assertEqual(
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)
通过:
self.assertEqual(
np.array(
[(1,1)],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[(1,1)],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)
这是一个错误还是我做错了什么?
我只能假设 unittest.TestCase.assertEqual
使用 __eq__
方法,该方法在 numpy.ndarray
对象中 elementwise 相等。因此,在两个空数组上使用 ==
returns 一个空布尔数组,即 falsy:
>>> arr1
rec.array([],
dtype=[('time', '<M8[ns]'), ('end_time', '<i8')])
>>> arr2
rec.array([],
dtype=[('time', '<M8[ns]'), ('end_time', '<i8')])
>>> bool(arr1 == arr2)
False
现在,在您的第二种情况下,您正在处理另一种特殊情况,即形状为 (1,)
的数组,这是具有单个元素的两个记录数组的元素相等的结果。本质上,对于具有单个项目的数组,真实性是元素的真实性:
>>> bool(np.array([1]))
True
>>> bool(np.array([0]))
False
>>> bool(np.array([{}]))
False
>>> bool(np.array([{'a':1}]))
True
>>> bool(np.array([object()]))
True
因此,使用您的数组:
>>> arr3 = np.array(
... [(1,1)],
... dtype=[
... ('time', 'datetime64[ns]'),
... ('end_time', int)
... ]
... ).view(np.recarray)
>>> arr4 = np.array(
... [(1,1)],
... dtype=[
... ('time', 'datetime64[ns]'),
... ('end_time', int)
... ]
... ).view(np.recarray)
>>> arr3.size, arr4.size
(1, 1)
>>> arr3 == arr4
rec.array([ True],
dtype=bool)
>>> bool(arr3 == arr4)
True
请注意,在任何情况下,如果结果数组的 .size
大于 1,那么如果您尝试计算真值,就会出现这个臭名昭著的错误,因此:
>>> np.array([1, 1]) == np.array([1, 1])
array([ True, True], dtype=bool)
>>> bool(np.array([1, 1]) == np.array([1, 1]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
>>>
@juanpa.arrivillaga 是正确的。但除此之外,您应该注意,最好使用 numpy.testing
模块对 NumPy 数组进行测试。例如:
np.testing.assert_equal(
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray),
np.array(
[],
dtype=[
('time', 'datetime64[ns]'),
('end_time', int)
]
).view(np.recarray)
)