Home > OS >  Numpy.any() between two indices of a 1D array multiple times in one step
Numpy.any() between two indices of a 1D array multiple times in one step

Time:12-24

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.

  • Related