python - tutorial - Ordenando una matriz numpy 2D por múltiples ejes
numpy tutorial español pdf (7)
EDITAR: eliminó la mala respuesta.
Aquí hay una manera de hacerlo usando una matriz estructurada intermedia:
from numpy import array
a = array([[3, 2], [6, 2], [3, 6], [3, 4], [5, 3]])
b = a.flatten()
b.dtype = [(''x'', ''<i4''), (''y'', ''<i4'')]
b.sort()
b.dtype = ''<i4''
b.shape = a.shape
print b
que da el resultado deseado:
[[3 2]
[3 4]
[3 6]
[5 3]
[6 2]]
Sin embargo, no estoy seguro de si esta es la mejor manera de hacerlo.
Tengo una matriz numpy 2D de forma (N, 2) que tiene N puntos (coordenadas xey). Por ejemplo:
array([[3, 2],
[6, 2],
[3, 6],
[3, 4],
[5, 3]])
Me gustaría ordenarlo de manera que mis puntos estén ordenados por coordenadas x, y luego por y en los casos donde la coordenada x sea la misma. Entonces, la matriz de arriba debería verse así:
array([[3, 2],
[3, 4],
[3, 6],
[5, 3],
[6, 2]])
Si esta fuera una lista de Python normal, simplemente definiría un comparador para hacer lo que quiero, pero hasta donde puedo decir, la función de ordenamiento de numpy no acepta comparadores definidos por el usuario. ¿Algunas ideas?
EDIT: gracias por las ideas! Configuré un caso de prueba rápido con 1000000 puntos enteros aleatorios y comparaté los que podía ejecutar (lo siento, no puedo actualizar el numpy en este momento).
Mine: 4.078 secs
mtrw: 7.046 secs
unutbu: 0.453 secs
El paquete numpy_indexed (descargo de responsabilidad: soy su autor) se puede usar para resolver este tipo de problemas de procesado en nd-array de una manera eficiente totalmente vectorizada:
import numpy_indexed as npi
npi.sort(a) # by default along axis=0, but configurable
El título dice "ordenar matrices 2D". Aunque el interlocutor utiliza una matriz en forma de (N,2)
, es posible generalizar la solución de unutbu para trabajar con cualquier matriz (N,M)
, ya que eso es lo que las personas realmente podrían estar buscando.
Uno podría transpose
la matriz y usar la notación de lexsort
con el step
negativo para pasar todas las columnas a la orden lexsort
en orden inverso:
>>> import numpy as np
>>> a = np.random.randint(1, 6, (10, 3))
>>> a
array([[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]])
Encontré una forma de hacerlo:
from numpy import array
a = array([(3,2),(6,2),(3,6),(3,4),(5,3)])
array(sorted(sorted(a,key=lambda e:e[1]),key=lambda e:e[0]))
Es bastante terrible tener que ordenar dos veces (y usar la función sorted
pitón simple en lugar de una especie de numpy más rápido), pero encaja muy bien en una línea.
Estaba luchando con lo mismo y solo recibí ayuda y resolví el problema. Funciona sin problemas si su matriz tiene nombres de columna (matriz estructurada) y creo que esta es una forma muy sencilla de ordenar utilizando la misma lógica que Excel:
array_name[array_name[[''colname1'',''colname2'']].argsort()]
Tenga en cuenta los doble paréntesis que encierran los criterios de clasificación. Y, por supuesto, puede usar más de 2 columnas como criterios de clasificación.
Puede usar np.complex_sort
. Esto tiene el efecto secundario de cambiar sus datos a punto flotante, espero que eso no sea un problema:
>>> a = np.array([[3, 2], [6, 2], [3, 6], [3, 4], [5, 3]])
>>> atmp = np.sort_complex(a[:,0] + a[:,1]*1j)
>>> b = np.array([[np.real(x), np.imag(x)] for x in atmp])
>>> b
array([[ 3., 2.],
[ 3., 4.],
[ 3., 6.],
[ 5., 3.],
[ 6., 2.]])
Usando 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()
devuelve una vista si a
es C_CONTIGUOUS
. Si eso es cierto, el método de @ ars , ligeramente modificado mediante el uso de ravel
lugar de flatten
, ofrece una buena manera de ordenar a
in situ :
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''])
Como b
es una vista de a
, sorting b
ordena a
:
print(a)
# [[3 2]
# [3 4]
# [3 6]
# [5 3]
# [6 2]]