How do I effectively turn a numpy boolean array into a threshold boolean array?

I am using Python 2.7 and NumPy to work with large arrays of booleans.

I have an array A, something like this:

>>> A
array([[[False, False, True, True, True],
        [False, False, False, True, True],
        [False, False, True, True, True],
        [False, False, False, True, True],
        [False, False, False, False, True]],

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

      

I need to include it in a boolean array like this:

>>> B
array([[[True, False, True, True, True],
        [True, True, False, True, True],
        [True, False, True, True, True],
        [True, True, False, True, True],
        [True, True, True, False, True]],

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

      

So the idea is that the last value of False

each row should remain, and any other value should become True

. I need to create it in order to use it as a mask for another array.

Is there a way to do this with NumPy without using loops for

(which are pretty slow)?

+3


source to share


4 answers


You can also use the xor operator ^

for this purpose. Just "shift the left" array one and add values True

to the right, and then xor the new and old array:

A = np.array([[False, False, True, True, True],
              [False, False, False, True, True],
              [False, False, True, True, True],
              [False, False, False, True, True],
              [False, False, False, False, True]])

X = np.hstack((A[:,1:], 
               np.array(np.ones((A.shape[0], 1)), dtype=np.bool))))
>>> array([[False, True, True, True, True],
           [False, False, True, True, True],
           [False, True, True, True, True],
           [False, False, True, True, True],
           [False, False, False, True, True]])

np.invert(A ^ X)
>>> array([[True, False, True, True, True],
           [True, True, False, True, True],
           [True, False, True, True, True],
           [True, True, False, True, True],
           [True, True, True, False, True]])

      



This only works if all values ​​are False

left and only values ​​follow True

.

+3


source


Here's one way that works for your array (and also works for arrays with more complex strings like [F, T, T, F, T]

):

>>> x = 4 - np.argmin(A[:,:,::-1], axis=2)[:,:,np.newaxis]
>>> (np.arange(5) * np.ones_like(A)) != x
array([[[ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True,  True,  True, False,  True]],

       [[False,  True,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True]]], dtype=bool)

      



Explanation:

  • Flip the array A

    by axis=2

    and use argmin

    along that axis to get the index of the first value False

    .

  • We need to know the index of the last occurrence False

    in A

    (not the first occurrence in an inverted array). This is the depth of the array (i.e. 5), minus 1, minus the index found in the previous step.

  • Add a new array of indices compatible with A

    by adding a new axis ( axis=2

    ). Call this new array of indices x

    .

  • Create an array with the same dimensions as A

    where each row axis=2

    is np.arange(5)

    . The required boolean array is found by testing for the inequality of this constructed array with x

    .

+3


source


If you are inverting the array, you can use numpy.nonzero

to find all (initially) false entries and then take the last one in each line from that. Then you can use it to build an array of masks.

+1


source


This is a simple problem. You need to select each line. Find False positions with np.where () and put True at those positions, except for the last one denoted by index [- 1] . This is done in the code below:

>>> import numpy as np
>>> A=np.array([[[False, False, True, True, True],
         [False, False, False, True, True],
         [False, False, True, True, True],
         [False, False, False, True, True],
         [False, False, False, False, True]],

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

>>> for mat in A:
     opmat=[]
     for arr in mat:
         index=np.where(arr==False)
         arr[index[0][:-1]]=True
         opmat.append(arr)
     out.append(opmat)

>>> out=np.array(out)
>>> out
array([[[ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True, False,  True,  True,  True],
        [ True,  True, False,  True,  True],
        [ True,  True,  True, False,  True]],

       [[False,  True,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True],
        [False,  True,  True,  True,  True],
        [ True, False,  True,  True,  True]]], dtype=bool)

      

0


source







All Articles