简体   繁体   中英

numpy: applying argsort to an array

The argsort() function returns a matrix of indices that can be used to index the original array so that the result would match the sort() result.

Is there a way to apply those indices? I have two arrays, one is the array used for obtaining the sort order, and another is some associated data.

I would like to compute assoc_data[array1.argsort()] but that doesn't seem to work.

Here's an example:

z=array([1,2,3,4,5,6,7])
z2=array([z,z*z-7])
i=z2.argsort()

z2=array([[ 1,  2,  3,  4,  5,  6,  7],
          [-6, -3,  2,  9, 18, 29, 42]])
i =array([[1, 1, 1, 0, 0, 0, 0],
          [0, 0, 0, 1, 1, 1, 1]])

I would like to apply i to z2 (or another array with associated data) but I'm not sure how to do so.

This is probably overkill, but this will work in the nd case:

import numpy as np
axis = 0
index = list(np.ix_(*[np.arange(i) for i in z2.shape]))
index[axis] = z2.argsort(axis)
z2[index]

# Or if you only need the 3d case you can use np.ogrid.

axis = 0
index = np.ogrid[:z2.shape[0], :z2.shape[1], :z2.shape[2]]
index[axis] = z2.argsort(axis)
z2[index]

You're lucky I just got my masters degree in numpyology.

>>> def apply_argsort(a, axis=-1):
...     i = list(np.ogrid[[slice(x) for x in a.shape]])
...     i[axis] = a.argsort(axis)
...     return a[i]
... 
>>> a = np.array([[1,2,3,4,5,6,7],[-6,-3,2,9,18,29,42]])
>>> apply_argsort(a,0)
array([[-6, -3,  2,  4,  5,  6,  7],
       [ 1,  2,  3,  9, 18, 29, 42]])

For an explanation of what's going on, see my answer to this question .

Use np.take_along_axis

np.take_along_axis(z2, i, axis=1)
Out[31]: 
array([[ 1,  2,  3,  4,  5,  6,  7],
       [-6, -3,  2,  9, 18, 29, 42]])

Aha, figured it out.

In [274]: z2[i,range(z2.shape[1])]
Out[274]:
array([[-6, -3,  2,  4,  5,  6,  7],
       [ 1,  2,  3,  9, 18, 29, 42]])

I had this problem recently (using a.argsort(axis=something) to sort b ). Here is my implementation, with no lists if one cannot afford the run time:

#For the example
import numpy as np
shape=(2,2,3,2)
t=np.random.randint(10,size=np.array(shape).prod()).reshape(shape)

#The axis to sort by
sortby=-1

#The actual sorting
x=t.swapaxes(sortby,-1)  #I actually only know to do the final dimension, so I cheat
a=np.argsort(x,axis=-1)
p = np.array(x.shape[:-1]).prod()
x.T[a.T].T.reshape(p**2,x.shape[-1])[::p+1].reshape(x.shape).swapaxes(sortby,-1)

I am not sure why this works, but it seems to work for any dimensions and sorting axis.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM