Se si annulla una matrice, gli elementi più bassi diventano gli elementi più alti e viceversa. Pertanto, gli indici degli n
elementi più alti sono:
(-avgDists).argsort()[:n]
Un altro modo di ragionare su questo, come menzionato nei commenti , è osservare che i grandi elementi stanno arrivando per ultimi nell'argsort. Quindi, puoi leggere dalla coda dell'argsort per trovare gli n
elementi più alti:
avgDists.argsort()[::-1][:n]
Entrambi i metodi sono O (n log n) nella complessità temporale, perché qui la argsort
chiamata è il termine dominante. Ma il secondo approccio ha un bel vantaggio: sostituisce una negazione O (n) dell'array con una sezione O (1) . Se si lavora con array di piccole dimensioni all'interno di loop, è possibile che si ottengano alcuni miglioramenti delle prestazioni evitando tale negazione e se si utilizzano array di grandi dimensioni, è possibile risparmiare sull'utilizzo della memoria perché la negazione crea una copia dell'intero array.
Si noti che questi metodi non danno sempre risultati equivalenti: se viene richiesta un'implementazione dell'ordinamento stabile argsort
, ad esempio passando l'argomento della parola chiave kind='mergesort'
, la prima strategia manterrà la stabilità dell'ordinamento, ma la seconda strategia romperà la stabilità (ovvero le posizioni di uguale gli articoli verranno invertiti).
Tempi di esempio:
Utilizzando un piccolo array di 100 galleggianti e una lunghezza di 30 code, il metodo di visualizzazione è stato di circa il 15% più veloce
>>> 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)
Per array più grandi, l'argsort è dominante e non vi è alcuna differenza temporale 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)
Si prega di notare che il commento di nedim di seguito non è corretto. Il troncamento prima o dopo l'inversione non fa alcuna differenza in termini di efficienza, poiché entrambe queste operazioni stanno solo spostando una vista dell'array in modo diverso e non copiando effettivamente i dati.
ids = np.array(avgDists).argsort()[-n:]
?