bard
bard

Reputation: 3052

Combining 3 boolean masks in Python

I have 3 lists:

a = [True, False, True]
b = [False, False, True]
c = [True, True, False]

When I type

a or b or c

I want to get back a list that's

[True, True, True]

but I'm getting back

[True, False, True]

Any ideas on why? And how can I combine these masks?

Upvotes: 15

Views: 22789

Answers (8)

rer
rer

Reputation: 1268

This is a good place to use one of python's asterisk functions (*args, **kwargs), which will allow you to pass 3 or 300000 lists.

    a = [True, False, True]
    b = [False, False, True]
    c = [True, True, False]
    data_lists = [a,b,c]

Here you use * to expand that list as arguments, zip to rearrange your data into columns (as lists), and any to check if any cell in that column is True.

    [any(l) for l in zip(*data_lists)]
    [True, True, True]

If you're working with a lot of lists it's the same, e.g.

    import numpy as np
    data_lists =  [[True if (i == j) else False for i in range(7)] for j in range(7)]
    np.matrix(data_lists)
    matrix([[ True, False, False, False, False, False, False],
            [False,  True, False, False, False, False, False],
            [False, False,  True, False, False, False, False],
            [False, False, False,  True, False, False, False],
            [False, False, False, False,  True, False, False],
            [False, False, False, False, False,  True, False],
            [False, False, False, False, False, False,  True]])
    [any(l) for l in zip(*data_lists)]
    [True, True, True, True, True, True, True]

Upvotes: 1

Dawn
Dawn

Reputation: 3628

how about

result = numpy.logical_or(a, b, c)
print(result)

Upvotes: 2

retox
retox

Reputation: 21

Here is how to do it fast (large arrays) using numpy:

import numpy as np
a = [True, False, True,...]
b = [False, False, True,...]
c = [True, True, False,...]
res = (np.column_stack((a,b,c)).any(axis=1)
print res

Note that a becomes the first column, b the second, and so on when using np.column_stack(). Then do a np.any() (logical OR) on that array along axis=1 which will compare the first elements of a,b, and c, and so on, and so on; resulting in a boolean vector that is the same length as the vectors you want to compare.

Upvotes: 2

Developer
Developer

Reputation: 8400

How about this:

from numpy import asarray as ar

a = [True, False, True]
b = [False, False, True]
c = [True, True, False]

Try:

>>> ar(a) | ar(b) | ar(c)                  #note also the use `|` instead of `or`
array([ True, True, True], dtype=bool)

So no need for zip etc.

Upvotes: 13

jscs
jscs

Reputation: 64002

Your or operators are comparing the lists as entire objects, not their elements. Since a is not an empty list, it evaluates as true, and becomes the result of the or. b and c are not even evaluated.

To produce the logical OR of the three lists position-wise, you have to iterate over their contents and OR the values at each position. To convert a bunch of iterables into a list of their grouped elements, use zip(). To check if any element in an iterable is true (the OR of its entire contents), use any(). Do these two at once with a list comprehension:

mask = [any(tup) for tup in zip(a, b, c)]

Upvotes: 13

Matteo Italia
Matteo Italia

Reputation: 126837

or returns the first operand if it evaluates as true, and a non-empty list evaluates as true; so, a or b or c will always return a if it's a non-empty list.

Probably you want

[any(t) for t in zip(a, b, c)]

(this works also for element-wise and if you replace any with all)

Upvotes: 7

Christian Tapia
Christian Tapia

Reputation: 34156

Try this:

a = [True, False, True]
b = [False, False, True]
c = [True, True, False]

res = [a[i] or b[i] or c[i] for i in range(len(a))]
print res

Upvotes: 2

falsetru
falsetru

Reputation: 369164

a is treated as true because it contains values; b, c is not evaluated.

>>> bool([])
False
>>> bool([True])
True
>>> bool([False])
True

>>> [False] or [True]
[False]

According to Boolean Operations:

The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.

Upvotes: 3

Related Questions