Considere o seguinte código:
avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]
Isso me dá índices dos n
menores elementos. É possível usar esse mesmo argsort
em ordem decrescente para obter os índices dos n
elementos mais altos?
ids = np.array(avgDists).argsort()[-n:]
?[3, 1, 2]
. Sua linha produz[2, 1, 3]
(se n == 3 como exemplo)ids = np.array(avgDists).argsort()[-n:][::-1]
. O problema é evitar fazer uma cópia de toda a lista, que é o que você obtém quando adiciona uma-
na frente dela. Não relevante para o pequeno exemplo do OP, poderia ser para casos maiores.np.array(avgDists).argsort()[::-1][:n]
fará isso. Além disso, se você estiver usando um numpy, fique num numpy. Primeiro converter a lista para um array:avgDist=np.array(avgDists)
então torna-seavgDist.argsort()[::-1][:n}
Respostas:
Se você negar uma matriz, os elementos mais baixos se tornam os elementos mais altos e vice-versa. Portanto, os índices dos
n
elementos mais altos são:Outra maneira de raciocinar sobre isso, como mencionado nos comentários , é observar que os grandes elementos estão chegando por último no argsort. Portanto, você pode ler a partir do final do argsort para encontrar os
n
elementos mais altos:Ambos os métodos são O (n log n) na complexidade do tempo, porque a
argsort
chamada é o termo dominante aqui. Mas a segunda abordagem tem uma boa vantagem: ela substitui uma negação de O (n) da matriz por uma fatia de O (1) . Se você estiver trabalhando com pequenas matrizes dentro de loops, poderá obter alguns ganhos de desempenho ao evitar essa negação e, se estiver trabalhando com grandes matrizes, poderá economizar no uso de memória, pois a negação cria uma cópia de toda a matriz.Observe que esses métodos nem sempre fornecem resultados equivalentes: se uma implementação de classificação estável for solicitada
argsort
, por exemplo, passando o argumento de palavra-chavekind='mergesort'
, a primeira estratégia preservará a estabilidade da classificação, mas a segunda estratégia quebrará a estabilidade (ou seja, as posições de igual itens serão revertidos).Exemplo de tempos:
Usando uma pequena variedade de 100 carros alegóricos e um comprimento de 30 cauda, o método de visualização foi cerca de 15% mais rápido
Para matrizes maiores, o argsort é dominante e não há diferença de tempo significativa
Observe que o comentário do nedim abaixo está incorreto. A truncagem antes ou depois da reversão não faz diferença na eficiência, pois essas duas operações estão apenas apresentando uma visão da matriz de maneira diferente e, na verdade, não estão copiando dados.
fonte
np.array(avgDists).argsort()[:-n][::-1]
Assim como Python, isso
[::-1]
inverte a matriz retornadaargsort()
e[:n]
fornece os últimos n elementos:A vantagem desse método é que
ids
é uma visão do avgDists:(O 'OWNDATA' sendo falso indica que esta é uma visualização, não uma cópia)
Outra maneira de fazer isso é algo como:
O problema é que a maneira como isso funciona é criar um negativo de cada elemento na matriz:
E cria uma cópia para fazer isso:
Portanto, se você cronometrar cada um, com este conjunto de dados muito pequeno:
O método view é substancialmente mais rápido (e usa 1/2 da memória ...)
fonte
Você pode usar os comandos flip
numpy.flipud()
ounumpy.fliplr()
para obter os índices em ordem decrescente após a classificação usando oargsort
comando É o que eu costumo fazer.fonte
Em vez de usar,
np.argsort
você pode usarnp.argpartition
- se você precisar apenas dos índices dos n elementos mais baixos / mais altos.Isso não requer a classificação de toda a matriz, mas apenas a parte de que você precisa, mas observe que a "ordem dentro da sua partição" é indefinida; portanto, embora ele forneça os índices corretos, eles podem não ser pedidos corretamente:
fonte
Você pode criar uma cópia da matriz e multiplicar cada elemento por -1.
Como efeito, os elementos anteriores maiores se tornariam os menores.
Os indeces dos n menores elementos da cópia são os n maiores elementos do original.
fonte
-array
Como o @Kanmani sugeriu, uma implementação mais fácil de interpretar pode ser usada
numpy.flip
, como no seguinte:Ao usar o padrão de visitante em vez de funções de membro, é mais fácil ler a ordem das operações.
fonte
Com o seu exemplo:
Obtenha índices de n valores máximos:
Classifique-os em ordem decrescente:
Obtenha resultados (para n = 4):
fonte
Outra maneira é usar apenas um '-' no argumento argsort como em: "df [np.argsort (-df [:, 0])]", desde que df seja o dataframe e você queira classificá-lo pela primeira vez coluna (representada pelo número da coluna '0'). Mude o nome da coluna conforme apropriado. Obviamente, a coluna deve ser numérica.
fonte