We'll explore certain caveats while testing numpy code.
Use np.allclose when comparing numpy arrays. Beware of nan.
In [1]:
import numpy as np
In [2]:
def test_mul():
arr = np.array([0.0, 1.0, 1.1])
v, expected = 1.1, np.array([0.0, 1.1, 1.21])
assert arr * v == expected, 'bad multiplication'
test_mul()
This is due to the fact that when we compare two numpy arrays with == we'll get an array of boolean values comparing each element.
In [3]:
np.array([1,2,3]) == np.array([1, 1, 3])
Out[3]:
And the truch value of an array (as the error says) is ambiguous.
In [4]:
bool(np.array([1, 2, 3]))
We need to use np.all to check that all elements are equal.
In [5]:
np.all([True, True, True])
Out[5]:
In [6]:
def test_mul():
arr = np.array([0.0, 1.0, 1.1])
v, expected = 1.1, np.array([0.0, 1.1, 1.21])
assert np.all(arr * v == expected), 'bad multiplication'
test_mul()
This is due to the fact that floating points are not exact.
In [7]:
1.1 * 1.1
Out[7]:
This is not a bug in Python but how floating points are implemented. You'll get the same result in C, Java, Go ... To overcome this we're going to use np.allclose.
BTW: If you're really intersted in floating points, read this article.
In [8]:
def test_mul():
arr = np.array([0.0, 1.0, 1.1])
v, expected = 1.1, np.array([0.0, 1.1, 1.21])
assert np.allclose(arr * v, expected), 'bad multiplication'
test_mul()
In [9]:
def test_div():
arr1, arr2 = np.array([1.0, np.inf, 2.0]), np.array([2.0, np.inf, 2.0])
expected = np.array([0.5, np.nan, 1.0])
assert np.allclose(arr1 / arr2, expected), 'bad nan'
test_div()
This is due to the fact the nan does not equal itself.
In [10]:
np.nan == np.nan
Out[10]:
To check is a number is nan we need to use np.isnan
In [11]:
np.isnan(np.inf/np.inf)
Out[11]:
We have two options to solve this:
nan to numbersequal_nan argument to np.allclose
In [12]:
def test_div():
arr1, arr2 = np.array([1.0, np.inf, 2.0]), np.array([2.0, np.inf, 2.0])
expected = np.array([0.5, np.nan, 1.0])
result = arr1 / arr2
result[np.isnan(result)] = 0.0
expected[np.isnan(expected)] = 0.0
assert np.allclose(result, expected), 'bad nan'
test_div()
In [13]:
def test_div():
arr1, arr2 = np.array([1.0, np.inf, 2.0]), np.array([2.0, np.inf, 2.0])
expected = np.array([0.5, np.nan, 1.0])
assert np.allclose(arr1 / arr2, expected, equal_nan=True), 'bad nan'
test_div()
In [ ]: