I have a 1D numpy array of booleans and I need to check if there is a True element between two indices in the 1D array multiple times in one step (i.e. no looping).
An example:
my_data = np.array([False, True, True, False, False, False, True, False])
inds2check = np.array([[0, 3],
[3, 5],
[6, 7]])
And I want the following result:
output = np.array([True, False, True])
How is this possible in Python with Numpy?
Note 1: I can change the size of inds2check
from 2D to 1D if needed.
Note 2: The ranges between the lower and upper indices are not of equal length. A 2D array of the ranges between the lower and upper indices themselves results in a numpy array of dtype object containing many numpy arrays of dtype np.int64. This type of array cannot be used to index another array. (Only a 2D array of dtype np.int can be used to index another array).
CodePudding user response:
Unfortunately I think you have to iterate it, but the cost depends only on the output's size. In your exemple, you will need iterate only 3 times.
import numpy as np
data = np.array([False, True, True, False, False, False, True, False])
inds = np.array([[0, 3],
[3, 5],
[6, 7]])
output = [np.any(data[a:b]) for i, (a, b) in enumerate(inds)]
output = np.array(output)
CodePudding user response:
Why not just iterate it:
my_data = np.array([False, True, True, False, False, False, True, False])
def true_between(first, second):
index = -1
if first > second:
print("Bad indices")
for i in range(first 1, second):
if my_data[i]:
print(f"YAY TRUE ITEM IN {i}")
index = i
return index
print(f"NO TRUE ITEM WAS FOUND")
return index
CodePudding user response:
Create an array containing the indices of my_data
and then use broadcasting and logic to find the elements of interest:
my_data = np.array([False, True, True, False, False, False, True, False])
inds2check = np.array([[0, 3],
[3, 5],
[6, 7]])
my_inds = np.array(range(0, len(my_data)))
a = my_inds[:,np.newaxis] >= inds2check[np.newaxis,:,0]
b = my_inds[:,np.newaxis] < inds2check[np.newaxis,:,1]
c = np.logical_and(np.logical_and(a, b), my_data[:,np.newaxis])
np.any(c, axis=0)
The arrays a
, b
and c
have the same number of rows as there are elements in my_data
with a column for each range given in inds2check
.
First we create a mask for each column to find the entries of my_data
(a & b
) then we find the true values ((a & b) & c)
). Finally, we use np.any
to find which columns contain a true value.