Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Numpy: sort by key function

Is there a way to sort the rows of a numpy ndarray using a key (or comparator) function, without resorting to converting to a python list?

In particular, I need to sort according to this function:

c1,c2= 4,7
lambda row: c1*(row[1]/c2)+row[0]

I realise one possible solution would be to generate a vector with the key value of each row, but how would one sort according to it? Should one seek to convert such vector into a index vector somehow?

order= c1*(matrix[:,1]/c2)+matrix[:,0]
indexes= order_to_index( order )
return matrix[ indexes ]

Is this realistic?

like image 846
loopbackbee Avatar asked Oct 13 '12 22:10

loopbackbee


2 Answers

For a more explicit answer, suppose we have an array x and want to sort the rows according to some function func which takes a row of x and outputs a scalar.

x[np.apply_along_axis(func, axis=1, arr=x).argsort()]

For this example

c1, c2 = 4, 7
x = np.array([
    [0, 1],
    [2, 3],
    [4, -5]
])
x[np.apply_along_axis(lambda row: c1 * / c2 * row[1] + row[0], 1, x).argsort()]

Out:

array([[ 0,  1],
       [ 4, -5],
       [ 2,  3]])

In this case, np.apply_along_axis isn't even necessary.

x[(c1 / c2 * x[:,1] + x[:,0]).argsort()]

Out:

array([[ 0,  1],
       [ 4, -5],
       [ 2,  3]])
like image 114
Dillon Bowen Avatar answered Nov 05 '22 22:11

Dillon Bowen


your approach is right, it is similar to the Schwartzian transform or Decorate-Sort-Undecorate (DSU) idiom

As I said you can use the numpy function np.argsort. It does the work of your order_to_index.

like image 33
Ruggero Turra Avatar answered Nov 05 '22 22:11

Ruggero Turra