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:
(-avgDists).argsort()[:n]
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:
avgDists.argsort()[::-1][:n]
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-chave kind='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
>>> avgDists = np.random.rand(100)
>>> n = 30
>>> timeit (-avgDists).argsort()[:n]
1.93 µs ± 6.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
1.64 µs ± 3.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
1.64 µs ± 3.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Para matrizes maiores, o argsort é dominante e não há diferença de tempo significativa
>>> avgDists = np.random.rand(1000)
>>> n = 300
>>> timeit (-avgDists).argsort()[:n]
21.9 µs ± 51.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
21.7 µs ± 33.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
21.9 µs ± 37.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
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.
ids = np.array(avgDists).argsort()[-n:]
?