How to get the relative complement of a boolean numpy array and another?

Viewed 633

Let's say I have two numpy arrays:

>>> v1
array([ True, False, False, False,  True])
>>> v2
array([False, False,  True,  True,  True])

I'm trying to retrieve an array that has the same length (5) and contains True in each position where v1==True AND v2==False. That would be:

array([True, False,  False,  False,  False])

Is there a quick way in numpy, something like logical_not() but considering v1 as the reference and v2 as the query?

3 Answers

You just need to use the right bitwise operators:

v1 & ~v2
# array([ True, False, False, False, False])

For boolean values, logical and bitwise operations are the same. It is therefore quite idiomatic to write

v1 & ~v2

However, this is a bitwise operation, and produces a potentially unnecessary temp array. You can not write v1 and not v2 as much as you'd like to because python expects to convert the inputs to single boolean values. Instead, you have to call the logical_and and logical_not ufuncs:

np.logical_and(v1, np.logical_not(v2))

The nice thing is that you can avoid the temp array, or even write directly to a buffer of your choice:

result = np.empty_like(v1)
np.logical_not(v2, out=result)
np.logical_and(v1, result, out=result)

You can even do the whole thing in-place (in v2):

np.logical_and(v1, np.logical_not(v2, out=v2), out=v2)

You can make use of bitwise operators here:

>>> v1 & ~v2
array([ True, False, False, False, False])
Related