Reoder the columns of each row of a numpy array ba

2019-08-02 09:35发布

问题:

We have a main array called main_arr, and we want to transform it into another array called result with the same size, using a guide_arr, again with the same size:

import numpy as np
main_arr = np.array([[3, 7, 4], [2, 5, 6]])
guide_arr = np.array([[2, 0, 1], [0, 2, 1]])
result = np.zeros(main_arr.shape)

we need the result to equal to:

if np.array_equal(result, np.array([[7, 4, 3], [2, 6, 5]])):
    print('success!')

How should we use guide_arr?

guide_arr[0,0] is 2, meaning that result[0,2] = main_arr[0,0]

guide_arr[0, 1] is 0 meaning that result[0, 0] = main_arr[0, 1]

guide_arr[0, 2] is 1 meaning that result[0, 1] = main_arr[0,2]

The same goes for row 1.

In summary, items in main_arr should be reordered (within a row, row never changes) so that their new column index equals the number in guide_arr.

回答1:

In [199]: main_arr = np.array([[3, 7, 4], [2, 5, 6]])
     ...: guide_arr = np.array([[2, 0, 1], [0, 2, 1]])
     ...: 

The usual way of reordering columns, where the order differs by row, is with indexing like this:

In [200]: main_arr[np.arange(2)[:,None],guide_arr]
Out[200]: 
array([[4, 3, 7],
       [2, 6, 5]])

The arange(2)[:,None] is a column array that broadcasts with the (2,3) index array.

We can apply the same idea to using guide_arr to identify columns in the result:

In [201]: result = np.zeros_like(main_arr)
In [202]: result[np.arange(2)[:,None], guide_arr] = main_arr
In [203]: result
Out[203]: 
array([[7, 4, 3],
       [2, 6, 5]])

This may clarify how the broadcasting works:

In [204]: np.broadcast_arrays(np.arange(2)[:,None], guide_arr)
Out[204]: 
[array([[0, 0, 0],
        [1, 1, 1]]), 
 array([[2, 0, 1],
        [0, 2, 1]])]