Sorting a 2D Numpy Array by Multiple Axes

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]]

Sorting A 2-Dimensional Array on Multiple Axes

Why don't you try python's sorted:

sorted(tasks, key=lambda x: (x[2],x[0]))

Output:

[['UYWEQ', '2017-04-23', '2017-07-18', 'Corey', 'Kyle', 'Reuben', 'Kai'],
['DNMDC', '2017-06-19', '2017-08-07', 'Kaleb', 'Kai', 'Kyle', 'Reuben'],
['NSXEN', '2017-08-20', '2017-09-18', 'Kai'],
['LIVNH', '2017-11-01', '2017-12-24', 'Kaleb', 'Kai'],
['LNWBN', '2017-08-13', '2017-12-24', 'Corey', 'Kyle', 'Kaleb', 'Reuben']]

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]]

How to sort a 2d numpy array by the columns with the biggest sum

I'm not sure if your solution is incorrect, but it is certainly more complicated than necessary:

>>> a = np.array([[5, 3, 13],
[1, 2, 20],
[6, 2, 6]])

>>> a[:, a.sum(axis=0).argsort()] # sort columns small-to-large
array([[ 3, 5, 13],
[ 2, 1, 20],
[ 2, 6, 6]])

>>> a[:, (a.sum(axis=0)*-1).argsort()] # multiply sums by -1 to sort large-to-small
array([[13, 5, 3],
[20, 1, 2],
[ 6, 6, 2]])

Sorting arrays in NumPy by column

@steve's answer is actually the most elegant way of doing it.

For the "correct" way see the order keyword argument of numpy.ndarray.sort

However, you'll need to view your array as an array with fields (a structured array).

The "correct" way is quite ugly if you didn't initially define your array with fields...

As a quick example, to sort it and return a copy:

In [1]: import numpy as np

In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])

In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]:
array([[0, 0, 1],
[1, 2, 3],
[4, 5, 6]])

To sort it in-place:

In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None

In [7]: a
Out[7]:
array([[0, 0, 1],
[1, 2, 3],
[4, 5, 6]])

@Steve's really is the most elegant way to do it, as far as I know...

The only advantage to this method is that the "order" argument is a list of the fields to order the search by. For example, you can sort by the second column, then the third column, then the first column by supplying order=['f1','f2','f0'].

Numpy sorting 2d array by descending and take first N from each row

Using numpy.argsort() returns an array of indices for the sorted array. As such, what your out_arr1 lets you know is where on each row to find the highest values.

If you are to continue this way, what you would need to do is for each row in in_arr (hereby written as in_arr[i]) take values found at the first 3 indices in out_arr1[i].

What that means is that out_arr1[i, 0] tells you where the highest value in in_arr on row i is located. In our case, out_arr1[0, 0] = 3, which means the highest value in row 0 is 40 (on index 3)

Doing this, the 3 largest numbers on each row are represented by out_arr1[0, 0], out_arr1[0, 1], out_arr1[0, 2] and out_arr1[1, 0], out_arr1[1, 1], out_arr1[1, 2].

to get the desired output, we would need something along the lines of:

final_arr = numpy.array([in_arr[0, out_arr1[0, 0], in_arr[0, out_arr1[0, 1], in_arr[0, out_arr1[0, 2], in_arr[1, out_arr1[1, 0], in_arr[1, out_arr1[1, 1], in_arr[1, out_arr1[1, 2]])

This however, is less than elegant, and there is another, easier solution to your problem.

Using numpy.sort() instead of numpy.argsort() we can return the exact values of in_arr sorted along an axis. By doing that, we no longer need to use an output index to find our 3 highest values, as they are the first 3 in our new output.

Considering out_arr2 as the output from numpy.sort(), the final array would look like:

final_arr = numpy.array([[out_arr[0, 0], out_arr[0, 1], out_arr[0, 2]], [out_arr[1, 0], out_arr[1, 1], out_arr[1, 2]]])

How to using numpy.argsort on a 2D array to sort another 2D array

np.take_along_axis has an example using argsort:

>>> a = np.array([[10, 30, 20], [60, 40, 50]])

We can sort either by using sort directly, or argsort and this function

>>> np.sort(a, axis=1)
array([[10, 20, 30],
[40, 50, 60]])
>>> ai = np.argsort(a, axis=1); ai
array([[0, 2, 1],
[1, 2, 0]])
>>> np.take_along_axis(a, ai, axis=1)
array([[10, 20, 30],
[40, 50, 60]])

This streamlines a process of applying ai to the array itself. We can do that directly, but it requires a bit more thought about what the index actually represents.

In this example, ai are index values along axis 1 (values like 0,1,or 2). This (2,3) has to broadcast with a (2,1) array for axis 0:

In [247]: a[np.arange(2)[:,None], ai]
Out[247]:
array([[10, 20, 30],
[40, 50, 60]])

How to sort a 2D array of two columns, from large to small, by the second column?

Assuming your array is as below, you could do:

import numpy as np

representative_models = np.array([[' A1', '1347'],
[' A4', '1381'],
[' Q3', '1417'],
[' A3', '1929'],
[' A6', '748'],
[' Q2', '822'],
[' Q5', '877'],
[' A5', '882']])

# convert last column to int and arg-sort in decreasing order [::-1]
order = np.argsort(representative_models[:, 1].astype(int))[::-1]

# simply index on the input array
result = representative_models[order, :]

print(result)

Output

[[' A3' '1929']
[' Q3' '1417']
[' A4' '1381']
[' A1' '1347']
[' A5' '882']
[' Q5' '877']
[' Q2' '822']
[' A6' '748']]

How to sort each row of a 3D numpy array by another 2D array?

If I understand you correctly, you want this:

norms = np.linalg.norm(a,axis=2) # shape(3,4)
indices = np.argsort(norms , axis=1)
np.take_along_axis(a, indices[:,:,None], axis=1)

output for your example:

[[[0.4236548  0.64589411]
[0.60276338 0.54488318]
[0.5488135 0.71518937]
[0.43758721 0.891773 ]]

[[0.07103606 0.0871293 ]
[0.79172504 0.52889492]
[0.96366276 0.38344152]
[0.56804456 0.92559664]]

[[0.0202184 0.83261985]
[0.46147936 0.78052918]
[0.77815675 0.87001215]
[0.97861834 0.79915856]]]


Related Topics



Leave a reply



Submit