Wenn Sie ein Array negieren, werden die niedrigsten Elemente zu den höchsten Elementen und umgekehrt. Daher sind die Indizes der n
höchsten Elemente:
(-avgDists).argsort()[:n]
Eine andere Möglichkeit, dies zu begründen, besteht, wie in den Kommentaren erwähnt , darin, zu beobachten, dass die großen Elemente im Argsort an letzter Stelle stehen. Sie können also am Ende des Argsorts lesen, um die n
höchsten Elemente zu finden :
avgDists.argsort()[::-1][:n]
Beide Methoden sind zeitliche Komplexität von O (n log n) , da der argsort
Aufruf hier der dominierende Begriff ist. Der zweite Ansatz hat jedoch einen schönen Vorteil: Er ersetzt eine O (n) -Negation des Arrays durch ein O (1) -Slice. Wenn Sie mit kleinen Arrays in Schleifen arbeiten, können Sie einige Leistungssteigerungen erzielen, wenn Sie diese Negation vermeiden. Wenn Sie mit großen Arrays arbeiten, können Sie Speicherplatz sparen, da durch die Negation eine Kopie des gesamten Arrays erstellt wird.
Beachten Sie, dass diese Methoden nicht immer gleichwertige Ergebnisse liefern: Wenn eine stabile Sortierimplementierung angefordert wird argsort
, z. B. durch Übergeben des Schlüsselwortarguments kind='mergesort'
, behält die erste Strategie die Sortierstabilität bei, die zweite Strategie unterbricht jedoch die Stabilität (dh die Positionen gleich) Artikel werden umgekehrt).
Beispielzeiten:
Bei Verwendung einer kleinen Anordnung von 100 Schwimmern und einer Länge von 30 Schwanz war die Ansichtsmethode etwa 15% schneller
>>> 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)
Bei größeren Arrays ist der Argsort dominant und es gibt keinen signifikanten Zeitunterschied
>>> 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)
Bitte beachten Sie, dass der Kommentar von nedim unten falsch ist. Ob vor oder nach dem Umkehren abgeschnitten werden soll, spielt keine Rolle für die Effizienz, da beide Vorgänge nur eine unterschiedliche Ansicht des Arrays anzeigen und keine Daten tatsächlich kopieren.
ids = np.array(avgDists).argsort()[-n:]
?