Ordenar matrices en NumPy por columna

Resuelto asked hace 14 años • 16 respuestas

¿Cómo ordeno una matriz NumPy por su enésima columna?

Por ejemplo, dado:

a = array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

Quiero ordenar las filas apor la segunda columna para obtener:

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])
 avatar May 13 '10 22:05
Aceptado

Para ordenar por la segunda columna de a:

a[a[:, 1].argsort()]
Steve Tjoa avatar May 13 '2010 15:05 Steve Tjoa

La respuesta de @steve es en realidad la forma más elegante de hacerlo.

Para conocer la forma "correcta", consulte el argumento de la palabra clave de orden de numpy.ndarray.sort

Sin embargo, necesitarás ver tu matriz como una matriz con campos (una matriz estructurada).

La forma "correcta" es bastante fea si inicialmente no definiste tu matriz con campos...

Como ejemplo rápido, para ordenarlo y devolver una copia:

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

Para ordenarlo en el lugar:

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 realmente es la forma más elegante de hacerlo, hasta donde yo sé...

La única ventaja de este método es que el argumento "orden" es una lista de campos para ordenar la búsqueda. Por ejemplo, puede ordenar por la segunda columna, luego por la tercera columna y luego por la primera columna proporcionando orden=['f1','f2','f0'].

Joe Kington avatar May 13 '2010 16:05 Joe Kington

Puede ordenar varias columnas según el método de Steve Tjoa utilizando una clasificación estable como mergesort y ordenando los índices desde las columnas menos significativas hasta las más significativas:

a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]

Esto ordena por columna 0, luego 1, luego 2.

J.J avatar Jul 05 '2016 01:07 J.J

En caso de que alguien quiera utilizar la clasificación en una parte crítica de sus programas, aquí hay una comparación de rendimiento para las diferentes propuestas:

import numpy as np
table = np.random.rand(5000, 10)

%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop

%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop

import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop

Entonces, parece que la indexación con argsort es el método más rápido hasta ahora...

prl900 avatar Feb 25 '2016 10:02 prl900