I want to test if two numpy arrays are (close to) equal, so I've been using the np.allclose
function. The only problem is, it returns True
if given a two-dimensional matrix and a three-dimensional matrix of equal elements.
import numpy as np
x = np.array([[3.14159265, -0.1], [-0.1, 0.1]])
y = np.array([[math.pi, -0.1], [-0.1, 0.1]])
z1 = np.array([[[3.14159265, -0.1], [-0.1, 0.1]],
[[3.14159265, -0.1], [-0.1, 0.1]]])
z2 = np.array([[[math.pi, -0.1], [-0.1, 0.1]],
[[math.pi, -0.1], [-0.1, 0.1]]])
np.allclose(x,y)
# Returns true, as expected
np.allclose(x,z1)
# Also returns true, even though matrices are different shapes. Unwanted.
Now, I know about np.array_equal
, which compares elements and shape, but it doesn't allow me to test if the elements are close, only if they are equal. For instance,
np.array_equal(x,y)
Returns False
Is there a function I can use that will return true for (x,y)
and (z1,z2)
but false for (x,z1)
in this case?
What's happening is that allclose
broadcasts its input. This allows comparisons with similarly shaped arrays (e.g. 3
and [3, 3, 3]
) following the broadcasting rules.
For your purposes, have a look at the numpy.testing
functions, specifically np.testing.assert_allclose
or assert_array_almost_equal
, which will check for shape as well as values. (I don't remember the difference between those two offhand, but it relates to the way they calculate floating point differences.)
These are particularly handy if you're using assert-based unit testing.
Most (all?) of the numpy.testing.assert_*
functions check for array shape as well as value equality.
For example:
In [1]: import numpy as np
In [2]: np.testing.assert_allclose([1], [[1]])
Which yields:
AssertionError:
Not equal to tolerance rtol=1e-07, atol=0
(shapes (1,), (1, 1) mismatch)
x: array([1])
y: array([[1]])
Another useful (and currently not as well documented as it could be) thing to know about these functions is that they compare NaN
's as equal.
For example, this will succeed:
In [3]: np.testing.assert_allclose([np.nan], [np.nan])
While numpy.allclose
will return False
for the same case:
In [4]: np.allclose([np.nan], [np.nan])
Out[4]: False
On a side note, numpy.isclose
(but not allclose
) has an equal_nan
kwarg to control this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With