MadMonty
MadMonty

Reputation: 887

Indexing numpy array with bounds checking

Suppose I have some random numpy array:

>>> x = np.random.randn(10, 4, 4)

So this can be viewed as 10 4x4 arrays. Now, I also have some coordinates with respect to each of these arrays:

>>> coords.shape
(10, 4, 4, 2)

and a particular element of this array might look like the following:

>>> coords[i][j][k]
array([ 2,  2])

Now, I'd like to create an array, y of size (10, 4, 4), where y[i][j][k] = x[coords[i][j][k]] if coords[i][j][k] is in bounds, and 0 otherwise.

I've tried doing something like the following:

>>> y = np.where(np.logical_and(
                 np.all(coords >= 0, axis = 3), 
                 np.all(coords <= 3, axis = 3)), 
                 x[tuple(coords)], 0)

But I can't quite get the broadcasting rules correct, and I'm getting errors.

For example, say we have,

>>> x = np.array([
                 [[1., 2.],
                  [4., 5.]],
                 [[6., 7.],
                  [8., 9.]]])

with,

>>> coords = np.array([
                       [[[0,-1], [0, 0]],
                        [[1, 1], [1, 0]]],
                       [[[1, 1], [1, 0]],
                        [[7, 2], [0, 0]]]
                      ])

Then, I'd somehow like to get

y = np.array([
             [[0., 1.],
              [5., 4.]],
             [[9., 8.],
              [0., 6.]]]) 

How can I achieve this in Python?

Upvotes: 0

Views: 2526

Answers (1)

Divakar
Divakar

Reputation: 221574

Seems like a bit of adavnced-indexing work was needed and should work for generic n-dim cases -

m,n = x.shape[0], x.shape[-1]
mask = (coords < n).all((-1)) & (coords >=0).all((-1))
v_coords = np.where(mask[:,:,:,None],coords,0)
out = x[np.arange(m)[:,None,None], v_coords[...,0], v_coords[...,1]]
out[~mask] = 0

Upvotes: 1

Related Questions