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)?
source to share
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
.
source to share
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
byaxis=2
and useargmin
along that axis to get the index of the first valueFalse
. -
We need to know the index of the last occurrence
False
inA
(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 indicesx
. -
Create an array with the same dimensions as
A
where each rowaxis=2
isnp.arange(5)
. The required boolean array is found by testing for the inequality of this constructed array withx
.
source to share
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.
source to share
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)
source to share