Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting a 2D numpy array by multiple axes

I have a 2D numpy array of shape (N,2) which is holding N points (x and y coordinates). For example:

array([[3, 2],        [6, 2],        [3, 6],        [3, 4],        [5, 3]]) 

I'd like to sort it such that my points are ordered by x-coordinate, and then by y in cases where the x coordinate is the same. So the array above should look like this:

array([[3, 2],        [3, 4],        [3, 6],        [5, 3],        [6, 2]]) 

If this was a normal Python list, I would simply define a comparator to do what I want, but as far as I can tell, numpy's sort function doesn't accept user-defined comparators. Any ideas?


EDIT: Thanks for the ideas! I set up a quick test case with 1000000 random integer points, and benchmarked the ones that I could run (sorry, can't upgrade numpy at the moment).

Mine:   4.078 secs  mtrw:   7.046 secs unutbu: 0.453 secs 
like image 642
perimosocordiae Avatar asked Apr 24 '10 23:04

perimosocordiae


People also ask

How can we sort a 2D NumPy array based on two columns?

Sorting 2D Numpy Array by column at index 1 Select the column at index 1 from 2D numpy array i.e. It returns the values at 2nd column i.e. column at index position 1 i.e. Now get the array of indices that sort this column i.e. It returns the index positions that can sort the above column i.e.

How do you sort a 2D NumPy array based on one column?

NumPy arrays can be sorted by a single column, row, or by multiple columns or rows using the argsort() function. The argsort function returns a list of indices that will sort the values in an array in ascending value.

How do you sort a 2D NumPy array in descending order?

Sort the rows of a 2D array in descending order The code axis = 1 indicates that we'll be sorting the data in the axis-1 direction, and by using the negative sign in front of the array name and the function name, the code will sort the rows in descending order.

What is the rank of NumPy array?

Rank of the array is the number of singular values of the array that are greater than tol. Input vector or stack of matrices. Threshold below which SVD values are considered zero. If tol is None, and S is an array with singular values for M, and eps is the epsilon value for datatype of S , then tol is set to S.


1 Answers

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]] 
like image 135
unutbu Avatar answered Sep 22 '22 06:09

unutbu