Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test if two numpy arrays are (close to) equal, including shape

Tags:

python

numpy

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?

like image 731
C_Z_ Avatar asked Sep 30 '15 20:09

C_Z_


1 Answers

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.

like image 150
Joe Kington Avatar answered Sep 28 '22 04:09

Joe Kington