Tengo una lista numérica:
myList = [1, 2, 3, 100, 5]
Ahora si ordeno esta lista para obtener [1, 2, 3, 5, 100]
. Lo que quiero son los índices de los elementos de la lista original en el orden ordenado, es decir, [0, 1, 2, 4, 3]
la función de clasificación de ala MATLAB que devuelve valores e índices.
Respuestas:
Si está usando numpy, tiene disponible la función argsort ():
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Esto devuelve los argumentos que ordenarían la matriz o la lista.
fuente
Algo así como el siguiente:
enumerate(myList)
le da una lista que contiene tuplas de (índice, valor):Ordena la lista pasándola
sorted
y especificando una función para extraer la clave de clasificación (el segundo elemento de cada tupla; para esolambda
sirve. Finalmente, el índice original de cada elemento ordenado se extrae usando la[i[0] for i in ...]
comprensión de la lista.fuente
itemgetter(1)
lugar de la función lambdaitemgetter
función en eloperator
módulo, FYI. Entonces hazlofrom operator import itemgetter
para usarlo.sorted_items, sorted_inds = zip(*sorted([(i,e) for i,e in enumerate(my_list)], key=itemgetter(1)))
x = [3,1,2]; numpy.argsort(x)
produce [1,2,0].fuente
Las respuestas con
enumerate
son agradables, pero personalmente no me gusta la lambda utilizada para ordenar por el valor. Lo siguiente solo invierte el índice y el valor, y lo ordena. Por lo tanto, primero se ordenará por valor, luego por índice.fuente
Respuesta actualizada con
enumerate
yitemgetter
:Comprima las listas juntas: el primer elemento en la tupla será el índice, el segundo es el valor (luego ordénelo usando el segundo valor de la tupla
x[1]
, x es la tupla)O usando
itemgetter
desde eloperator
módulo`:fuente
Hice una comprobación rápida del rendimiento de estos con perfplot (un proyecto mío) y descubrí que es difícil recomendar algo más que numpy (tenga en cuenta la escala de registro):
Código para reproducir la trama:
fuente
Si no quieres usar numpy,
es más rápido, como se demuestra aquí .
fuente
Esencialmente necesitas hacer un
argsort
, qué implementación necesita depende si desea usar bibliotecas externas (por ejemplo, NumPy) o si desea permanecer en Python puro sin dependencias.La pregunta que debe hacerse es: ¿quiere el
Desafortunadamente, el ejemplo en la pregunta no deja en claro lo que se desea porque ambos darán el mismo resultado:
Elegir el
argsort
implementaciónSi tiene NumPy a su disposición, simplemente puede usar la función
numpy.argsort
o el métodonumpy.ndarray.argsort
.Ya se mencionó una implementación sin NumPy en algunas otras respuestas, así que resumiré la solución más rápida de acuerdo con la respuesta de referencia aquí
Obteniendo los índices que ordenarían la matriz / lista
Para obtener los índices que ordenarían la matriz / lista, simplemente puede llamar
argsort
a la matriz o lista. Estoy usando las versiones de NumPy aquí, pero la implementación de Python debería dar los mismos resultadosEl resultado contiene los índices necesarios para obtener la matriz ordenada.
Dado que la matriz ordenada sería
[1, 2, 3, 4]
la matriz ordenada contiene los índices de estos elementos en el original.1
y está en el índice1
del original, por lo que el primer elemento del resultado es1
.2
está en el índice2
en el original, por lo que el segundo elemento del resultado es2
.3
está en el índice0
en el original, por lo que el tercer elemento del resultado es0
.4
y está en el índice3
en el original, por lo que el último elemento del resultado es3
.Obtener los índices que tendrían los elementos en la matriz / lista ordenada
En este caso, deberá aplicar
argsort
dos veces :En este caso :
3
, que es el tercer valor más grande, por lo que tendría un índice2
en la matriz / lista ordenada, por lo que el primer elemento es2
.1
, que es el valor más pequeño, por lo que tendría un índice0
en la matriz / lista ordenada para que el segundo elemento sea0
.2
, que es el segundo valor más pequeño, por lo que tendría un índice1
en la matriz / lista ordenada para que el tercer elemento sea1
.4
cuál es el valor más grande, por lo que tendría un índice3
en la matriz / lista ordenada, por lo que el último elemento es3
.fuente
Las otras respuestas son incorrectas.
Ejecutar
argsort
una vez no es la solución. Por ejemplo, el siguiente código:rinde lo
array([1, 2, 0], dtype=int64)
que no es lo que queremos.La respuesta debería ser correr
argsort
dos veces:da
array([2, 0, 1], dtype=int64)
como se esperaba.fuente
x[2]
(3) sea el elemento más pequeño yx[1]
(1) el elemento más grande (ya que la clasificación de enteros los ordena de menor a mayor valor). Además, con el ejemplo de OP, un solonp.argsort([1, 2, 3, 100, 5])
rendimientoarray([0, 1, 2, 4, 3])
, que parece ser el índice que quiere el OP.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
, obtenemos[0 1 2 4 5 3]
cuál está mal.arr[res]
rendimientosarray([ 1, 2, 3, 5, 9, 100])
, que parecen estar perfectamente bien, ya que esa matriz resultante está en orden (creciente).arr=[1,2,3,100, 5, 9]
, espero que la salida seainds=[0,1,2,5,3,4]
, porque este es el orden en el que ordenará los elementos (cada vez más): 1 está en el lugar de 0, 2 en el primer lugar, ..., 5 en el 3er lugar y 9 en el 4to lugar. Para obtener esa salida (inds
) necesito ejecutarargsort
dos veces, como mencioné.sort
, creo que el OP quiere la otra funcionalidad, comonp.argsort
se usa normalmente (donde se puede usararr[np.argsort[arr]]
para obtener la matriz ordenada, como en el último ejemplo de MATLAB). Su respuesta se aplica a este caso / pregunta en su lugar.Importar numpy como np
PARA ÍNDICE
argsort Devuelve los índices de S en orden ordenado
POR VALOR
fuente
Crearemos otra matriz de índices de 0 a n-1. Luego comprima esto en la matriz original y luego ordénelo según los valores originales.
``
fuente