Reputation: 1021
I am really confused on why this error is showing up. Here is my code:
import numpy as np
x = np.array([0, 0])
y = np.array([10, 10])
a = np.array([1, 6])
b = np.array([3, 7])
points = [x, y, a, b]
max_pair = [x, y]
other_pairs = [p for p in points if p not in max_pair]
>>>ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()
(a not in max_paix)
>>>ValueError: The truth ...
What confuses me is that the following works fine:
points = [[1, 2], [3, 4], [5, 7]]
max_pair = [[1, 2], [5, 6]]
other_pairs = [p for p in points if p not in max_pair]
>>>[[3, 4], [5, 7]]
([5, 6] not in max_pair)
>>>False
Why is this happening when using numpy arrays? Is not in/in
ambiguous for existance?
What is the correct syntax using any()\all()
?
Upvotes: 3
Views: 19276
Reputation: 7020
Numpy arrays define a custom equality operator, i.e. they are objects that implement the __eq__
magic function. Accordingly, the ==
operator and all other functions/operators that rely on such an equality call this custom equality function.
Numpy's equality is based on element-wise comparison of arrays. Thus, in return you get another numpy array with boolean values. For instance:
x = np.array([1,2,3])
y = np.array([1,4,5])
x == y
returns
array([ True, False, False], dtype=bool)
However, the in
operator in combination with lists requires equality comparisons that only return a single boolean value. This is the reason why the error asks for all
or any
. For instance:
any(x==y)
returns True
because at least one value of the resulting array is True
.
In contrast
all(x==y)
returns False
because not all values of the resulting array are True
.
So in your case, a way around the problem would be the following:
other_pairs = [p for p in points if all(any(p!=q) for q in max_pair)]
and print other_pairs
prints the expected result
[array([1, 6]), array([3, 7])]
Why so? Well, we look for an item p from points where any of its entries are unequal to the entries of all items q from max_pair.
Upvotes: 9
Reputation: 3094
Reason behind is that they're two different objects completely. np.array
has it's own operators that work on it.
They are named the same as the global operators any
and all
but don't work exactly the same, and that distinction is reflected in the fact they are methods of np.array
.
>>> x = np.array([0,9])
>>> x.any(axis=0)
True
>>> y = np.array([10, 10])
>>> y.all()
True
>>> y.all(axis=0)
True
meanwhile:
>>> bool([])
False
>>> bool([[]])
True
>>> bool([[]][0])
False
Notice how first result is false (in python2) an empty list is deemed False
. However a list with another list in it, even if that one is empty, is not False
but True
. Evaluating the inside list returns False
again because it's empty. Since any
and all
are defined over the conversion to bool
the results you see are different.
>>> help(all)
all(...)
all(iterable) -> bool
Return True if bool(x) is True for all values x in the iterable.
>>> help(any)
any(...)
any(iterable) -> bool
Return True if bool(x) is True for any x in the iterable.
See a better explanations for logical numpy operators here
Upvotes: 1