1

I have a 'list of arrays' and I order each of these arrays with argsort:

import numpy as np    
arr = np.array([[4, 2, 5], [4, 3, 1], [1, 5, 7], [1, 5, 4]])
idxs = arr.argsort(axis=1)
idxs
>>> array([[1, 0, 2],
           [2, 1, 0],
           [0, 1, 2],
           [0, 2, 1]])

For each of these 4 arrays I have 3x3 matrix that I save in a 'list of matrices':

arr2.shape
>>> (4, 3, 3)

I want to use idxs to sort the columns of each array. So for the first matrix I want to rearrange the columns like

m1 = arr2[0]
m1 = [:, [1, 0, 2]]

Just giving idxs in square brackets to arr2 won't work and even just trying to apply the idxs to the array they are coming from won't work:

arr[arr.argsort(arr, axis=1)].shape
>>> (4, 3, 3)
Pickniclas
  • 349
  • 1
  • 8
  • I am not sure I understand the question correctly, but you can sort all the values using [argsort](https://stackoverflow.com/questions/47044792/sort-invariant-for-numpy-argsort-with-multiple-dimensions), then the returned indices can directly be used on your array to sort all the items in the order returned by argsort, in any case `idx = argsort(); array[idx]`. Please update your question if this is not what you were looking for. – Thymen Dec 02 '20 at 15:34
  • I have re read your question again, the `[:, [2, 0, 1]]` is not a valid single assignment, that has confused me many times as well, but `[np.arange(3), [2, 0, 1]]` is a valid single assignment. – Thymen Dec 02 '20 at 15:38
  • [np.arange(3), [2, 0, 1]] won't work. Only, as suggested by Quang Hoang, arr[np.arange(arr.shape[0])[:,None], idxs] does the job for arr. But for arr2 it changes the rows instead of columns. – Pickniclas Dec 02 '20 at 16:09

1 Answers1

1

You can use pair indexing:

arr2 = np.arange(3*4*3).reshape(4,3,-1)

arr2[np.arange(arr2.shape[0])[:,None],:, idxs]

Output:

array([[[ 1,  4,  7],
        [ 0,  3,  6],
        [ 2,  5,  8]],

       [[11, 14, 17],
        [10, 13, 16],
        [ 9, 12, 15]],

       [[18, 21, 24],
        [19, 22, 25],
        [20, 23, 26]],

       [[27, 30, 33],
        [29, 32, 35],
        [28, 31, 34]]])
Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
  • Thank you very much for the answer. However, I want to use it to sort arr2. arr2[np.arange(arr2.shape[0])[:, None], idxs] swaps the rows. arr2[np.arange(arr2.shape[0])[:, None], idxs, :] also doesn't work. I could of course use swapaxes before, swap the rows and then swapaxes back. – Pickniclas Dec 02 '20 at 15:54
  • And concerning your note: I can do this to sort arr, but I want to use these indices to sort arr2. – Pickniclas Dec 02 '20 at 16:11
  • I tried this, but this didn't work, did it? The first array's column should be [1, 4, 7], but it's [3, 0, 6]. – Pickniclas Dec 02 '20 at 17:08
  • @Pickniclas sorry, pasted the wrong output. The first row is indeed `[1,4,7]`. notice the extra `:` in the indexing. You didn't mention this in your previous comment – Quang Hoang Dec 02 '20 at 18:17
  • Thanks, but still: The first column of arr2 is [0, 3, 6], the second is [1, 4, 7], but in your output these are rows now, instead of columns, aren't they? – Pickniclas Dec 03 '20 at 20:40