NumPy chained comparison with two predicates

In NumPy, I can generate a boolean array like this:

>>> arr = np.array([1, 2, 1, 2, 3, 6, 9])
>>> arr > 2
array([False, False, False, False,  True,  True,  True], dtype=bool)

How can we chain comparisons together? For example:

>>> 6 > arr > 2
array([False, False, False, False,  True,  False,  False], dtype=bool)

Attempting to do so results in the error message

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

AFAIK the closest you can get is to use &, |, and ^:

>>> arr = np.array([1, 2, 1, 2, 3, 6, 9])
>>> (2 < arr) & (arr < 6)
array([False, False, False, False,  True, False, False], dtype=bool)
>>> (2 < arr) | (arr < 6)
array([ True,  True,  True,  True,  True,  True,  True], dtype=bool)
>>> (2 < arr) ^ (arr < 6)
array([ True,  True,  True,  True, False,  True,  True], dtype=bool)

I don’t think you’ll be able to get a < b < c-style chaining to work.

Method 2

You can use the numpy logical operators to do something similar.

>>> arr = np.array([1, 2, 1, 2, 3, 6, 9])
>>> arr > 2
array([False, False, False, False,  True,  True,  True], dtype=bool)
>>>np.logical_and(arr>2,arr<6)
Out[5]: array([False, False, False, False,  True, False, False], dtype=bool)

Method 3

Chained comparisons are not allowed in numpy. You need to write both left and right comparisons separately, and chain them with bitwise operators. Also you’ll need to parenthesise both expressions due to operator precendence (|, & and ^ have a higher precedence). In this case, since you want both conditions to be satisfied you need an bitwise AND (&):

(2<arr) & (arr<6)
# array([False, False, False, False,  True, False, False])

It was actually proposed to make this possible in PEP 535, though it still remains deferred. In it there is an explanation on why this occurs. As posed in the question, chaining comparisons in such way, yields:

2<arr<6

ValueError: The truth value of an array with more than one element is ambiguous.
Use a.any() or a.all()

The problem here, is that python is internally expanding the above to:

2<arr and arr<6

Which is what causes the error, since and is implicitly calling bool, and NumPy only permits implicit coercion to a boolean value for single elements (not arrays with size>1), since a boolean array with many values does not evaluate neither to True or False. It is due to this ambiguity that this isn’t allowed, and evaluating an array in boolean context always yields a ValueError


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x