Search code examples
pythonnumpyvectorizationnumpy-ndarrayarray-broadcasting

How to change an array using advanced indexing and boolean array indexing without loops in numpy?


Problem:

A is a multidimensional array of two dimensions (i,j) and B is a boolean array of the same shape that I want to define according to the values of A.

I want to define B through two broadcasting indices:

  • i_b is an array that selects the indices of the first coordinate.
  • ij_b is a boolean array that selects the indices j given i has already been selected.

Code:

The code I programmed:

A = np.arange(50).reshape(5, 10) #shape: (i, j)
B = np.full(A.shape, False) #shape: (i, j)

#We pick first dimension
i_b = np.array([0, 2, 4])

#We pick second dimension given the first dimension has been chosen
ij_b = A[i_b]%2 == 0

#Change B according to i and ij
B[i_b][ij_b] = True

print(B[i_b][ij_b])

Output: [False False False False False False False False False False False False False False False].

The line B[i_b][ij_b] = True does not seem to change B. Why does it happen? How can I perform this operation to change B in a vectorized way?


I know I can write a loop that works:

for k in range(len(i_b)):
    B[i_b[k]][ij_b[k]] = True
print(B[i_b][ij_b])

Output: [ True True True True True True True True True True True True True True True]

But then it stops being vectorized.


Solution

  • As metioned in the documentation:

    Advanced indexing always returns a copy of the data (contrast with basic slicing that returns a view).

    We can solve the problem of the question (from Numpy: chained boolean indexing not properly updating boolean array without using np.where), using:

    B[i_b] = ij_b