Jeśli zanegujesz tablicę, najniższe elementy stają się najwyższymi elementami i odwrotnie. Dlatego wskaźniki n
najwyższych elementów to:
(-avgDists).argsort()[:n]
Innym sposobem uzasadnienia tego, jak wspomniano w komentarzach , jest zaobserwowanie, że duże elementy pojawiają się na końcu w argsort. Tak więc możesz czytać z ogona argsort, aby znaleźć n
najwyższe elementy:
avgDists.argsort()[::-1][:n]
Obie metody mają złożoność czasową O (n log n) , ponieważ argsort
wywołanie jest tutaj terminem dominującym. Ale drugie podejście ma dobrą zaletę: zastępuje negację O (n) tablicy wycięciem O (1) . Jeśli pracujesz z małymi tablicami wewnątrz pętli, możesz uzyskać pewien wzrost wydajności dzięki unikaniu tej negacji, a jeśli pracujesz z dużymi tablicami, możesz zaoszczędzić na zużyciu pamięci, ponieważ negacja tworzy kopię całej tablicy.
Zauważ, że metody te nie zawsze dają równoważne wyniki: jeśli wymagana jest stabilna implementacja sortowania argsort
, np. Poprzez przekazanie argumentu słowa kluczowegokind='mergesort'
, wówczas pierwsza strategia zachowa stabilność sortowania, ale druga strategia złamie stabilność (tj. Pozycje równe przedmioty zostaną odwrócone).
Przykładowe czasy:
Przy użyciu małej tablicy 100 pływaków i ogona o długości 30 metoda widoku była o około 15% szybsza
>>> 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)
W przypadku większych tablic dominuje argsort i nie ma znaczącej różnicy czasu
>>> 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)
Uwaga: poniższy komentarz nedim jest nieprawidłowy. To, czy obcinać przed czy po cofnięciu, nie ma różnicy w wydajności, ponieważ obie te operacje jedynie zmieniają widok tablicy inaczej i nie kopiują danych.
ids = np.array(avgDists).argsort()[-n:]
?