Home > Mobile >  How to use np.where multiple times without iteration?
How to use np.where multiple times without iteration?

Time:11-19

Note that this question is not about multiple conditions within a single np.where(), see this thread for that.


I have a numpy array arr1 with some numbers (without a particular structure):

arr0 = \
np.array([[0,3,0],
          [1,3,2],
          [1,2,0]])

and a list of all the entries in this array:

entries = [0,1,2,3]

I also have another array, arr1:

arr1 = \
np.array([[4,5,6],
          [6,2,4],
          [3,7,9]])

I would like to perform some function on multiple subsets of elements of arr1. A subset consts of numbers which are at the same position as arr0 entries with a cetrain value. Let this function be finding the max value. Performing the function on each subset via a list comprehension:

res = [np.where(arr0==index,arr1,0).max() for index in entries]

res is [9, 6, 7, 5]

As expected: 0 in arr0 is on the top left, top right, bottom right corner, and the biggest number from the top left, top right, bottom right entries of arr1 (ie 4, 6, 9) is 9. Rest follow with a similar logic.

How can I achieve this without iteration?

My actual arrays are much bigger than these examples.

CodePudding user response:

With broadcasting

res = np.where(arr0[...,None] == entries, arr1[...,None], 0).max(axis=(0, 1))

The result of np.where(...) is a (3, 3, 4) array, where slicing [...,0] would give you the same 3x3 array you get by manually doing the np.where with just entries[0], etc. Then taking the max of each 3x3 subarray leaves you with the desired result.

CodePudding user response:

It's more convenient to work in 1D case. You need to sort your arr0 then find starting indices for every group and use np.maximum.reduceat.

arr0_1D = np.array([[0,3,0],[1,3,2],[1,2,0]]).ravel()
arr1_1D = np.array([[4,5,6],[6,2,4],[3,7,9]]).ravel()
arg_idx = np.argsort(arr0_1D)
>>> arr0_1D[arg_idx]
array([0, 0, 0, 1, 1, 2, 2, 3, 3])
u, idx = np.unique(arr0_1D[arg_idx], return_index=True)
>>> idx
array([0, 3, 5, 7], dtype=int64)
>>> np.maximum.reduceat(arr1_1D[arg_idx], idx)
array([9, 6, 7, 5], dtype=int32)
  • Related