Sorting a 2D numpy array by multiple axes Sorting a 2D numpy array by multiple axes numpy numpy

Sorting a 2D numpy array by multiple axes


Using lexsort:

import numpy as np    a = np.array([(3, 2), (6, 2), (3, 6), (3, 4), (5, 3)])ind = np.lexsort((a[:,1],a[:,0]))    a[ind]# array([[3, 2],#       [3, 4],#       [3, 6],#       [5, 3],#       [6, 2]])

a.ravel() returns a view if a is C_CONTIGUOUS. If that is true, @ars's method, slightly modifed by using ravel instead of flatten, yields a nice way to sort a in-place:

a = np.array([(3, 2), (6, 2), (3, 6), (3, 4), (5, 3)])dt = [('col1', a.dtype),('col2', a.dtype)]assert a.flags['C_CONTIGUOUS']b = a.ravel().view(dt)b.sort(order=['col1','col2'])

Since b is a view of a, sorting b sorts a as well:

print(a)# [[3 2]#  [3 4]#  [3 6]#  [5 3]#  [6 2]]


The title says "sorting 2D arrays". Although the questioner uses an (N,2)-shaped array, it's possible to generalize unutbu's solution to work with any (N,M) array, as that's what people might actually be looking for.

One could transpose the array and use slice notation with negative step to pass all the columns to lexsort in reversed order:

>>> import numpy as np>>> a = np.random.randint(1, 6, (10, 3))>>> aarray([[4, 2, 3],       [4, 2, 5],       [3, 5, 5],       [1, 5, 5],       [3, 2, 1],       [5, 2, 2],       [3, 2, 3],       [4, 3, 4],       [3, 4, 1],       [5, 3, 4]])>>> a[np.lexsort(np.transpose(a)[::-1])]array([[1, 5, 5],       [3, 2, 1],       [3, 2, 3],       [3, 4, 1],       [3, 5, 5],       [4, 2, 3],       [4, 2, 5],       [4, 3, 4],       [5, 2, 2],       [5, 3, 4]])


The numpy_indexed package (disclaimer: I am its author) can be used to solve these kind of processing-on-nd-array problems in an efficient fully vectorized manner:

import numpy_indexed as npinpi.sort(a)  # by default along axis=0, but configurable