Reputation: 1124
I looking for indexing strategy how I can select sub-array(right-side) from original array(left-side) and then replace original array with sub-array(bottom). There are indexes to select for each row, e.g. for first row they are [1,3,0], and for last are [4,6,2]. Full selection matrix for the illustration below looks like this:
[[1,3,0],
[2,3,2],
[4,0,6],
[1,4,0],
[4,6,2]]
So far I can make only looping through rows of original array and replace values at column indexes. Is there solution without a loop?
+--------------------------------------+
| |
| +-----------------------+ |
| | | |
| +----------------------------+ | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
+ + + v v v
array([[ 0, 1, 2, 3, 4, 5, 6], 1, 3, 0,
[ 7, 8, 9, 10, 11, 12, 13], 9,10,9,
!14, 15, 16, 17,!18, 19,!20], 18,14,20,
[21, 22, 23, 24, 25, 26, 27], 22,25,21,
[28, 29, 30, 31, 32, 33, 34]]) 32,34,30
+ + + ^ ^ ^
| | | | | |
| +----------------+ | |
| | | |
| +-----------+ |
| |
+-------------------------------+
Final array is original array with replaced last indices from sub-array( which is selected from original array.
+------------+
array([[ 0, 1, 2, 3,| 1, 3, 0],|
[ 7, 8, 9, 10,| 9, 10, 9],|
[14, 15, 16, 17,|18, 14, 20],|
[21, 22, 23, 24,|22, 25, 21],|
[28, 29, 30, 31,|32, 34, 30]]|
+------------+
Solution with loop:
selection = np.array([[1,3,0],
[2,3,2],
[4,0,6],
[1,4,0],
[4,6,2]])
y = np.arange(35).reshape(5,7)
s = y.shape[1] - selection.shape[1]
e = y.shape[1]
for i in range(0, y.shape[0]):
y[i, s:e] = y[i, selection[i]]
>>> y
array([[ 0, 1, 2, 3, 1, 3, 0],
[ 7, 8, 9, 10, 9, 10, 9],
[14, 15, 16, 17, 18, 14, 20],
[21, 22, 23, 24, 22, 25, 21],
[28, 29, 30, 31, 32, 34, 30]])
Upvotes: 3
Views: 473
Reputation: 53029
Use broaodcasting and advanced indexing:
>>> y[:, 4:] = y[np.arange(5)[:, None], selection]
>>> y
array([[ 0, 1, 2, 3, 1, 3, 0],
[ 7, 8, 9, 10, 9, 10, 9],
[14, 15, 16, 17, 18, 14, 20],
[21, 22, 23, 24, 22, 25, 21],
[28, 29, 30, 31, 32, 34, 30]])
Upvotes: 2
Reputation: 59711
You can do it by creating the indices for the rows:
import numpy as np
a = np.array([[ 0, 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12, 13],
[14, 15, 16, 17, 18, 19, 20],
[21, 22, 23, 24, 25, 26, 27],
[28, 29, 30, 31, 32, 33, 34]])
idx = np.array([[1,3,0],
[2,3,2],
[4,0,6],
[1,4,0],
[4,6,2]])
rows = np.tile(np.arange(len(idx)), [idx.shape[1], 1]).T
# This array looks like this:
# [[0, 0, 0],
# [1, 1, 1],
# [2, 2, 2],
# [3, 3, 3],
# [4, 4, 4]]
a[:, -idx.shape[1]:] = a[rows, idx]
print(a)
Output:
array([[ 0, 1, 2, 3, 1, 3, 0],
[ 7, 8, 9, 10, 9, 10, 9],
[14, 15, 16, 17, 18, 14, 20],
[21, 22, 23, 24, 22, 25, 21],
[28, 29, 30, 31, 32, 34, 30]])
Upvotes: 2