Reputation: 887
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
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