Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Numpy recarray sort bidirectional

I have a structured numpy array, and I am sorting it by a order. It works pretty fine but in just one direction!

Descending:

sort(myStructuredArray,order=my_order)[::-1]

and

Ascending:

sort(myStructuredArray,order=my_order)

The order my_order is something like [col1,col2,-col3,col4,-col5,...,colN] and for some columns I would like to order it ascending like col1,col2 and colN and for others descending col3 and col5 (minus signal) . In this example I would like to sort my array first by col1 ascending, then by col2 ascending, then by col3 descending, then by col4 ascending, then by col5 descending and so on... How can I do that?

Thank you

like image 343
user2209128 Avatar asked Apr 12 '13 13:04

user2209128


1 Answers

You can do this with numpy.lexsort

In [1]: import numpy as np
In [2]: a = np.array([(4,0), (1,9), (1,0), (4,9)],
                     dtype=[('x',int),('y',float)])

In [3]: a
Out[3]: 
array([(4, 0.0), (1, 9.0), (1, 0.0), (4, 9.0)], 
      dtype=[('x', '<i8'), ('y', '<f8')])

In [4]: a['x']
Out[4]: array([4, 1, 1, 4])

In [5]: a['y']
Out[5]: array([ 0.,  9.,  0.,  9.])

The order priority of the arguments to lexsort are opposite that of np.sort(..., order=...). So, to sort first by descending 'x' and then by ascending 'y':

In [6]: a[np.lexsort((a['y'], -a['x']))]
Out[6]: 
array([(4, 0.0), (4, 9.0), (1, 0.0), (1, 9.0)], 
      dtype=[('x', '<i8'), ('y', '<f8')])

Notes:

  • This works assuming all your values are numerical (since the negative won't reverse string sorting).
  • I've seen somewhere the use of a['x'][::-1] as a key instead of -a['x'] but that's not working for me right now.
like image 52
askewchan Avatar answered Sep 21 '22 06:09

askewchan