Reputation: 1948
I have two arrays, one is a matrix of index pairs,
a = array([[[0,0],[1,1]],[[2,0],[2,1]]], dtype=int)
and another which is a matrix of data to access at these indices
b = array([[1,2,3],[4,5,6],[7,8,9]])
and I want to able to use the indices of a to get the entries of b
. Just doing:
>>> b[a]
does not work, as it gives one row of b for each entry in a
, i.e.
array([[[[1,2,3],
[1,2,3]],
[[4,5,6],
[4,5,6]]],
[[[7,8,9],
[1,2,3]],
[[7,8,9],
[4,5,6]]]])
when I would like to use the index pair in the last axis of a
to give the two indices of b
:
array([[1,5],[7,8]])
Is there a clean way of doing this, or do I need to reshape b
and combine the columns of a
in a corresponding manner?
In my actual problem a
has about 5 million entries, and b
is 100-by-100, I'd like to avoid for loops.
Upvotes: 2
Views: 1221
Reputation: 1193
A more general solution, whenever you want to use a 2D array of indices of shape (n,m) with arbitrary large dimension m, named inds
, in order to access elements of another 2D array of shape (n,k), named B
:
# array of index offsets to be added to each row of inds
offset = np.arange(0, inds.size, inds.shape[1])
# numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C
Result = np.take(B, offset[:,np.newaxis]+inds)
Another solution, which doesn't use np.take
and I find more intuitive, is the following:
B[np.expand_dims(np.arange(B.shape[0]), -1), inds]
The advantage of this syntax is that it can be used both for reading elements from B
based on inds
(like np.take
), as well as for assignment.
You can test this by using, e.g.:
B = 1/(np.arange(n*m).reshape(n,-1) + 1)
inds = np.random.randint(0,B.shape[1],(B.shape[0],B.shape[1]))
Upvotes: 0
Reputation: 3682
Actually, this works:
b[a[:, :, 0],a[:, :, 1]]
Gives array([[1, 5],
[7, 8]])
.
Upvotes: 2
Reputation: 13539
For this case, this works
tmp = a.reshape(-1,2)
b[tmp[:,0], tmp[:,1]]
Upvotes: 1