Question

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

Was it helpful?

Solution

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.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top