Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2d array boolean reduction

I've got a 2D array comprised of boolean values (True,False). I'd like to consolidate the array to a 1D based on a logical function of the contents.

e.g. Input:

[[True, True, False],
 [False, False, False],
 [True, True, True]]

Output (logical AND):

[False,
 False,
 True]

How would this be done without a loop ?

like image 236
DnRng Avatar asked Oct 15 '18 19:10

DnRng


5 Answers

You can use Python's built-in all method with a list-comprehension:

[all(x) for x in my_list]

If that's still too loopy for you, combine it with map:

map(all, my_list)

Note that map doesn't return a list in Python 3. If you want a list as your result, you can call list(map(all, my_list)) instead.

like image 96
Woody1193 Avatar answered Nov 12 '22 16:11

Woody1193


You can do this without NumPy too. Here is one solution using list comprehension. Explanation: It will loop over sub-lists and even if one of the items in each sub-list is False, it outputs False else True.

inp = [[True, True, False],[False, False, False],[True, True, True]]
out = [False if False in i else True for i in inp]
print (out)

# [False, False, True]

Alternative (less verbose) as suggested by Jean below:

out = [False not in i for i in inp]
like image 22
Sheldore Avatar answered Nov 12 '22 17:11

Sheldore


I'm assuming you want to apply logical ANDs to the rows. You can apply numpy.all.

>>> import numpy as np
>>> a = np.array([[True, True, False], [False, False, False], [True, True, True]])
>>> a
array([[ True,  True, False],
       [False, False, False],
       [ True,  True,  True]])
>>> 
>>> np.all(a, axis=1)
array([False, False,  True])

For a solution without numpy, you can use operator.and_ and functools.reduce.

>>> from operator import and_
>>> from functools import reduce
>>> 
>>> lst = [[True, True, False], [False, False, False], [True, True, True]]
>>> [reduce(and_, sub) for sub in lst]
[False, False, True]

edit: actually, reduce is a bit redundant in this particular case.

>>> [all(sub) for sub in lst]
[False, False, True]

does the job just as well.

like image 4
timgeb Avatar answered Nov 12 '22 18:11

timgeb


You can do this with numpy with the numpy.all function:

>>> import numpy as np
>>> arr = np.array([[True, True, False],
... [False, False, False],
... [True, True, True]]
... )
>>> np.all(arr, axis=1)
array([False, False,  True])

Here thus the i-th element is True if all elements of the i-th row are True, and False otherwise. Note that the list should be rectangular (all sublists should contain the same number of booleans).

In "pure" Python, you can use the all function as well, like:

>>> data = [[True, True, False], [False, False, False], [True, True, True]]
>>> list(map(all, data))
[False, False, True]

This approach will work as well if the "matrix" is not rectangular. Note that for an empty sublist, this will return True, since all elements in an empty sublist are True.

like image 3
Willem Van Onsem Avatar answered Nov 12 '22 17:11

Willem Van Onsem


You can also do this with map and reduce:

from functools import reduce

l = [[True, True, False],
    [False, False, False],
    [True, True, True]]

final = list(map(lambda x: reduce(lambda a, b: a and b, x), l))
print(final)
# [False, False, True]

The benefit here is that you can change the reduce function to something else (say, an OR or something more adventurous).

like image 3
slider Avatar answered Nov 12 '22 16:11

slider