Eu tenho uma lista numérica:
myList = [1, 2, 3, 100, 5]
Agora, se eu classificar esta lista para obter [1, 2, 3, 5, 100]
. O que eu quero é os índices dos elementos da lista original na ordem classificada, ou seja, [0, 1, 2, 4, 3]
--- a função de classificação ala MATLAB que retorna valores e índices.
Respostas:
Se você estiver usando numpy, você tem a função argsort () disponível:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.argsort.html
Isso retorna os argumentos que classificariam a matriz ou a lista.
fonte
Algo como o próximo:
enumerate(myList)
fornece uma lista contendo tuplas de (índice, valor):Você classifica a lista passando-a
sorted
e especificando uma função para extrair a chave de classificação (o segundo elemento de cada tupla;lambda
é para isso que serve. Finalmente, o índice original de cada elemento classificado é extraído usando a[i[0] for i in ...]
compreensão da lista.fonte
itemgetter(1)
em vez da função lambdaitemgetter
função nooperator
módulo, FYI. Então façafrom operator import itemgetter
para usá-lo.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)
gera [1,2,0].fonte
As respostas
enumerate
são boas, mas eu pessoalmente não gosto do lambda usado para classificar pelo valor. O seguinte apenas reverte o índice e o valor e classifica isso. Portanto, ele primeiro classifica por valor, depois por índice.fonte
Resposta atualizada com
enumerate
eitemgetter
:Compacte as listas: O primeiro elemento da tupla será o índice, o segundo é o valor (em seguida, classifique-o usando o segundo valor da tupla
x[1]
, x é a tupla)Ou usando
itemgetter
dooperator
módulo`:fonte
Fiz uma rápida verificação de desempenho nelas com o perfplot (um projeto meu) e constatei que é difícil recomendar qualquer outra coisa além de entorpecente (observe a escala de log):
Código para reproduzir o gráfico:
fonte
Se você não quiser usar numpy,
é mais rápido, como demonstrado aqui .
fonte
Essencialmente, você precisa fazer um
argsort
, de qual implementação você depende depende se você deseja usar bibliotecas externas (por exemplo, NumPy) ou se deseja permanecer em Python puro sem dependências.A pergunta que você precisa se perguntar é: você quer o
Infelizmente, o exemplo da pergunta não deixa claro o que é desejado, porque ambos darão o mesmo resultado:
Escolhendo a
argsort
implementaçãoSe você tiver o NumPy à sua disposição, poderá simplesmente usar a função
numpy.argsort
ou métodonumpy.ndarray.argsort
.Uma implementação sem NumPy já foi mencionada em algumas outras respostas, portanto, apenas recapitularei a solução mais rápida de acordo com a resposta de referência aqui
Obtendo os índices que ordenariam a matriz / lista
Para obter os índices que ordenariam a matriz / lista, você pode simplesmente chamar
argsort
a matriz ou a lista. Estou usando as versões do NumPy aqui, mas a implementação do Python deve fornecer os mesmos resultadosO resultado contém os índices necessários para obter a matriz classificada.
Como a matriz classificada seria,
[1, 2, 3, 4]
a matriz argsorted contém os índices desses elementos no original.1
e está no índice1
do original, portanto, o primeiro elemento do resultado é1
.2
está no índice2
no original, portanto, o segundo elemento do resultado é2
.3
está no índice0
no original, portanto, o terceiro elemento do resultado está0
.4
e está no índice3
no original, portanto, o último elemento do resultado é3
.Obtendo os índices que os elementos teriam na matriz / lista classificada
Nesse caso, você precisaria aplicar
argsort
duas vezes :Nesse caso :
3
, que é o terceiro maior valor, portanto, ele teria um índice2
na matriz / lista classificada, portanto, o primeiro elemento2
.1
, que é o menor valor, portanto, ele teria um índice0
na matriz / lista classificada, de modo que o segundo elemento é0
.2
, que é o segundo menor valor; portanto, ele teria um índice1
na matriz / lista classificada, de modo que o terceiro elemento é1
.4
qual é o maior valor, portanto, ele teria um índice3
na matriz / lista classificada, e o último elemento3
.fonte
As outras respostas estão erradas.
Correr
argsort
uma vez não é a solução. Por exemplo, o seguinte código:produz
array([1, 2, 0], dtype=int64)
que não é o que queremos.A resposta deve ser executar
argsort
duas vezes:dá
array([2, 0, 1], dtype=int64)
como esperado.fonte
x[2]
(3) o menor elemento ex[1]
(1) o maior elemento (já que a classificação de números inteiros os ordena do menor para o maior valor). Além disso, com o exemplo dos OPs, um úniconp.argsort([1, 2, 3, 100, 5])
rendimentoarray([0, 1, 2, 4, 3])
, que parece ser o índice que o OP deseja.arr = [1,2,3,100, 5, 9] res = np.argsort(arr) print(res)
, entendemos o[0 1 2 4 5 3]
que está errado.arr[res]
rendimentosarray([ 1, 2, 3, 5, 9, 100])
, o que parece estar perfeitamente bem, pois a matriz resultante está em ordem (crescente).arr=[1,2,3,100, 5, 9]
, espero que a saída sejainds=[0,1,2,5,3,4]
, porque esta é a ordem em que você ordenará os elementos (cada vez mais) - 1 está no lugar 0s, 2 no 1º lugar, ...., 5 no 3º lugar e 9 no 4º lugar. Para obter essa saída (inds
), preciso executarargsort
duas vezes, como mencionei.sort
, acho que o OP deseja a outra funcionalidade, da mesma forma quenp.argsort
normalmente é usada (onde é possível usararr[np.argsort[arr]]
para obter a matriz classificada, como no último exemplo do MATLAB). Sua resposta se aplica a este caso / pergunta .Importar numpy como np
PARA ÍNDICE
argsort Retorna os índices de S na ordem classificada
PARA VALOR
fonte
Criaremos outra matriz de índices de 0 a n-1. Em seguida, compacte-a na matriz original e classifique-a com base nos valores originais
`
fonte