NumPy: Compare two arrays element-wise
In NumPy, to compare two arrays (ndarray
) element-wise, use comparison operators such as >
or ==
, which return a Boolean ndarray
. You can also compare an array to a scalar value.
Additionally, NumPy offers functions like np.array_equal()
and np.array_equiv()
to check if two arrays are equal, and np.isclose()
and np.allclose()
to check if each or all elements are close.
The NumPy version used in this article is as follows. Note that functionality may vary between versions.
import numpy as np
print(np.__version__)
# 1.26.1
Compare two NumPy arrays element-wise with comparison operators
A Boolean ndarray
is returned
Consider the following two NumPy arrays (ndarray
) as examples.
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
b = np.arange(12).reshape(4, 3).T
print(b)
# [[ 0 3 6 9]
# [ 1 4 7 10]
# [ 2 5 8 11]]
Using comparison operators like <
, >
, <=
, >=
, ==
, !=
, each element is compared and a Boolean ndarray
is returned.
a_compare = a < b
print(a_compare)
# [[False True True True]
# [False False True True]
# [False False False False]]
print(type(a_compare))
# <class 'numpy.ndarray'>
print(a_compare.dtype)
# bool
Since comparisons are based on values, differing data types (dtype
) are not a problem.
b_float = b.astype(float)
print(b_float)
# [[ 0. 3. 6. 9.]
# [ 1. 4. 7. 10.]
# [ 2. 5. 8. 11.]]
print(b_float.dtype)
# float64
print(a == b_float)
# [[ True False False False]
# [False False False False]
# [False False False True]]
When comparing floating point numbers (float
) with ==
, be careful of inaccuracies. To allow for some tolerance, use np.isclose()
described below.
In NumPy, the shapes are aligned as much as possible by so-called broadcasting, even when comparing arrays with different shapes.
b_1d = np.arange(4, 8)
print(b_1d)
# [4 5 6 7]
print(a < b_1d)
# [[ True True True True]
# [False False False False]
# [False False False False]]
When comparing with a scalar value, each element is compared with that value.
print(a < 6)
# [[ True True True True]
# [ True True False False]
# [False False False False]]
It is also possible to compare the result of an operation. For example, to check if elements are even, you could use the following approach:
print(a % 2)
# [[0 1 0 1]
# [0 1 0 1]
# [0 1 0 1]]
print(a % 2 == 0)
# [[ True False True False]
# [ True False True False]
# [ True False True False]]
With np.count_nonzero()
, np.all()
, np.any()
np.count_nonzero()
counts the True
values in a Boolean ndarray
, indicating how many elements meet a condition.
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(a < 6)
# [[ True True True True]
# [ True True False False]
# [False False False False]]
print(np.count_nonzero(a < 6))
# 6
Use np.all()
to check if all elements are True
, and np.any()
to check if any element is True
. Both functions allow row-wise or column-wise checks with the axis
argument.
print(np.all(a < 6))
# False
print(np.all(a < 6, axis=1))
# [ True False False]
print(np.any(a < 6))
# True
print(np.any(a < 6, axis=1))
# [ True True False]
For more details on combining comparison operators with np.count_nonzero()
, np.all()
, and np.any()
, see the following article.
Compare with NaN
: np.isnan()
For example, NaN
can occur when reading a CSV file with missing data.
- NumPy: Read and write CSV files (np.loadtxt, np.genfromtxt, np.savetxt)
- NumPy: Replace NaN (np.nan) using np.nan_to_num() and np.isnan()
Since comparing NaN
with NaN
always returns False
, you need to use np.isnan()
to check for NaN
values.
a_nan = np.array([0, 1, np.nan])
print(a_nan)
# [ 0. 1. nan]
print(a_nan == np.nan)
# [False False False]
print(np.isnan(a_nan))
# [False False True]
Note that comparison to NaN
using <
or >
also returns False
.
print(a_nan > 0)
# [False True False]
Use np.array_equal()
or np.isclose()
, as mentioned later, if you want True
when NaN
values are at the same position.
For multiple conditions: &
, |
Python allows chaining conditions as follows:
x = 6
print(4 < x < 8)
# True
This syntax does not apply to ndarray
. To specify multiple conditions, write each condition separately and combine them using &
(AND) or |
(OR).
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# print(4 < a < 8)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
print((a > 4) & (a < 8))
# [[False False False False]
# [False True True True]
# [False False False False]]
Note that using and
or or
, or omitting parentheses, raises an error.
# print((a > 4) and (a < 8))
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
# print(a > 4 & a < 8)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
For more details on this error, see the following article.
The same applies when comparing three or more arrays. It is possible in Python syntax to compare them together.
x = 6
y = 6
z = 6
print(x == y == z)
# True
This is also not allowed for ndarray
. Combine conditions using &
or |
.
b = np.arange(12).reshape(4, 3).T
print(b)
# [[ 0 3 6 9]
# [ 1 4 7 10]
# [ 2 5 8 11]]
c = np.zeros((3, 4), int)
print(c)
# [[0 0 0 0]
# [0 0 0 0]
# [0 0 0 0]]
# print(a == b == c)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
print((a == b) & (b == c))
# [[ True False False False]
# [False False False False]
# [False False False False]]
Check if two arrays are equal: np.array_equal()
, np.array_equiv()
You can check if all elements of two arrays are equal using ==
and np.all()
.
a = np.array([0, 1, 2])
b = np.array([0, 1, 2])
c = np.array([3, 4, 5])
print(np.all(a == b))
# True
print(np.all(a == c))
# False
Alternatively, you can use the np.array_equal()
and np.array_equiv()
functions.
Specify array-like objects as the first and second arguments. If all elements are equal, these functions return True
, otherwise False
.
print(np.array_equal(a, b))
# True
print(np.array_equal(a, c))
# False
print(np.array_equiv(a, b))
# True
print(np.array_equiv(a, c))
# False
Like ==
, different data types (dtype
) are not a problem.
b_float = b.astype(float)
print(np.array_equal(a, b_float))
# True
print(np.array_equiv(a, b_float))
# True
np.array_equal()
returns False
if the shapes do not match, whereas np.array_equiv()
allows comparisons with a scalar or a broadcastable array.
ones = np.array([1, 1, 1])
print(np.array_equal(ones, 1))
# False
print(np.array_equiv(ones, 1))
# True
a_1d = np.array([0, 1, 2])
a_2d = np.array([[0, 1, 2], [0, 1, 2], [0, 1, 2]])
print(np.array_equal(a_1d, a_2d))
# False
print(np.array_equiv(a_1d, a_2d))
# True
Comparisons between NaN
values return False
, even if they are in the same position.
a_nan = np.array([np.nan, 1, 2])
b_nan = np.array([np.nan, 1, 2])
print(np.array_equal(a_nan, b_nan))
# False
print(np.array_equiv(a_nan, b_nan))
# False
print(np.all(a_nan == b_nan))
# False
NumPy 1.19 introduced equal_nan
as a third argument to np.array_equal()
, allowing comparisons between NaN
values to yield True
when set to True
. The default setting is False
.
print(np.array_equal(a_nan, b_nan, True))
# True
Check if each element of two arrays is close: np.isclose()
Floating point numbers (float
) are represented in binary internally, making it impossible to represent some decimal numbers exactly.
For example, 0.1 + 0.1 + 0.1
is not equal to 0.3
.
print(0.1 + 0.1 + 0.1)
# 0.30000000000000004
a = np.array([0.3, 0.1 + 0.1 + 0.1])
print(a)
# [0.3 0.3]
b = np.array([0.3, 0.3])
print(b)
# [0.3 0.3]
print(a == b)
# [ True False]
Note that the output of print()
is displayed as 0.3
in the above example because the default is to display up to 8 decimal places. You can change the setting with np.set_printoptions()
.
np.set_printoptions(precision=18)
print(a)
# [0.3 0.30000000000000004]
np.isclose()
checks if values are close element-wise within a tolerance. It is also possible to compare to a scalar or a broadcastable array.
print(np.isclose(a, b))
# [ True True]
print(np.isclose(a, 0.3))
# [ True True]
It can also compare scalar values, returning a scalar value.
print(np.isclose(0.1 + 0.1 + 0.1, 0.3))
# True
The allowable tolerance can be specified with the rtol
and atol
arguments. Defaults are rtol=1e-05
and atol=1e-08
. The determination of closeness is based on the following formula.
absolute(a - b) <= (atol + rtol * absolute(b)) numpy.isclose — NumPy v1.26 Manual
The math
module includes math.isclose()
, which uses a different formula for comparison.
For example, to consider it True
when the absolute difference is within 1
, configure the settings as follows.
print(np.isclose(100, 101))
# False
print(np.isclose(100, 101, rtol=0, atol=1))
# True
The equal_nan
argument, which defaults to False
, can be set to True
to treat comparisons between NaN
values as True
.
print(np.isclose(np.nan, np.nan))
# False
print(np.isclose(np.nan, np.nan, equal_nan=True))
# True
Note that comparisons of other values with NaN
are False
, even with equal_nan=True
.
a_nan = np.array([np.nan, 1, 2])
b_nan = np.array([np.nan, 1, np.nan])
print(np.isclose(a_nan, b_nan))
# [False True False]
print(np.isclose(a_nan, b_nan, equal_nan=True))
# [ True True False]
Check if all elements of two arrays are close: np.allclose()
np.allclose()
checks if two arrays are element-wise equal within a tolerance.
a = np.array([0.3, 0.1 + 0.1 + 0.1])
b = np.array([0.3, 0.3])
c = np.array([0.1, 0.3])
print(np.allclose(a, b))
# True
print(np.allclose(a, c))
# False
np.allclose()
is implemented as np.all(np.isclose(...))
and accepts the same arguments as np.isclose()
.
The allowable tolerance is specified by the rtol
and atol
arguments, with the same formula used in np.isclose()
.
a = np.array([99, 100, 101])
print(np.allclose(a, 100))
# False
print(np.allclose(a, 100, rtol=0, atol=1))
# True
It is also possible to compare to a scalar or a broadcastable array.
The equal_nan
argument, which defaults to False
, can also be specified. The default is equal_nan=False
.
a_nan = np.array([np.nan, 1, 2])
b_nan = np.array([np.nan, 1, 2])
print(np.allclose(a_nan, b_nan))
# False
print(np.allclose(a_nan, b_nan, equal_nan=True))
# True