Dlaczego numpy podaje ten wynik:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
kiedy spodziewałbym się, że to zrobi:
[3 2 0 1]
Najwyraźniej brakuje mi zrozumienia tej funkcji.
Dlaczego numpy podaje ten wynik:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
kiedy spodziewałbym się, że to zrobi:
[3 2 0 1]
Najwyraźniej brakuje mi zrozumienia tej funkcji.
Odpowiedzi:
Zgodnie z dokumentacją
Zwraca indeksy, które posortowałyby tablicę.
2
jest indeksem 0.0
.3
jest indeksem 0.1
.1
jest indeksem 1.41
.0
jest indeksem 1.48
.a = x.argsort()
, drukuj x[a]
, dostaniemyarray([ 0. , 0.1 , 1.41, 1.48])
[2, 3, 1, 0]
wskazuje, że najmniejszy element znajduje się pod indeksem 2, następny najmniejszy element pod indeksem 3, następnie indeks 1, a następnie indeks 0.
Istnieje kilka sposobów uzyskania wyniku, którego szukasz:
import numpy as np
import scipy.stats as stats
def using_indexed_assignment(x):
"https://stackoverflow.com/a/5284703/190597 (Sven Marnach)"
result = np.empty(len(x), dtype=int)
temp = x.argsort()
result[temp] = np.arange(len(x))
return result
def using_rankdata(x):
return stats.rankdata(x)-1
def using_argsort_twice(x):
"https://stackoverflow.com/a/6266510/190597 (k.rooijers)"
return np.argsort(np.argsort(x))
def using_digitize(x):
unique_vals, index = np.unique(x, return_inverse=True)
return np.digitize(x, bins=unique_vals) - 1
Na przykład,
In [72]: x = np.array([1.48,1.41,0.0,0.1])
In [73]: using_indexed_assignment(x)
Out[73]: array([3, 2, 0, 1])
To sprawdza, czy wszystkie dają ten sam wynik:
x = np.random.random(10**5)
expected = using_indexed_assignment(x)
for func in (using_argsort_twice, using_digitize, using_rankdata):
assert np.allclose(expected, func(x))
Te %timeit
testy porównawcze IPythona sugerują, że dla dużych tablic using_indexed_assignment
są najszybsze:
In [50]: x = np.random.random(10**5)
In [66]: %timeit using_indexed_assignment(x)
100 loops, best of 3: 9.32 ms per loop
In [70]: %timeit using_rankdata(x)
100 loops, best of 3: 10.6 ms per loop
In [56]: %timeit using_argsort_twice(x)
100 loops, best of 3: 16.2 ms per loop
In [59]: %timeit using_digitize(x)
10 loops, best of 3: 27 ms per loop
W przypadku małych tablic using_argsort_twice
może być szybsze:
In [78]: x = np.random.random(10**2)
In [81]: %timeit using_argsort_twice(x)
100000 loops, best of 3: 3.45 µs per loop
In [79]: %timeit using_indexed_assignment(x)
100000 loops, best of 3: 4.78 µs per loop
In [80]: %timeit using_rankdata(x)
100000 loops, best of 3: 19 µs per loop
In [82]: %timeit using_digitize(x)
10000 loops, best of 3: 26.2 µs per loop
Zauważ również, że stats.rankdata
daje ci to większą kontrolę nad tym, jak obsługiwać elementy o równej wartości.
argsort
zwraca indeksy posortowanej tablicy. Indeks posortowanych indeksów to ranga. Oto co argsort
powraca drugie wezwanie .
Jak mówi dokumentacjaargsort
:
Zwraca indeksy, które posortowałyby tablicę.
Oznacza to, że pierwszym elementem argsort jest indeks elementu, który powinien być sortowany jako pierwszy, drugi element to indeks elementu, który powinien być drugi itd.
Wydaje się, że chcesz, aby porządek rangi wartości był zapewniony przez scipy.stats.rankdata
. Pamiętaj, że musisz pomyśleć o tym, co się stanie, jeśli w szeregach są remisy.
numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)
Zwraca indeksy, które posortowałyby tablicę
Wykonaj pośrednie sortowanie wzdłuż danej osi, używając algorytmu określonego przez słowo kluczowe kind. Zwraca tablicę indeksów o tym samym kształcie, co dane indeksu wzdłuż danej osi w posortowanej kolejności.
Rozważ jeden przykład w Pythonie, mając listę wartości jako
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Teraz używamy funkcji argsort:
import numpy as np
list(np.argsort(listExample))
Wynik będzie
[0, 5, 6, 1, 3, 2, 4]
To jest lista indeksów wartości na liście Przykład, jeśli odwzorujesz te indeksy na odpowiednie wartości, otrzymamy następujący wynik:
[0, 0, 1, 2, 2000, 2456, 5000]
(Uważam, że ta funkcja jest bardzo przydatna w wielu miejscach, np. Jeśli chcesz posortować listę / tablicę, ale nie chcesz używać funkcji list.sort () (tj. Bez zmiany kolejności rzeczywistych wartości na liście), możesz użyć tego funkcjonować.)
Więcej informacji można znaleźć pod tym linkiem: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
wejście:
import numpy as np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()
wyjście:
tablica ([3, 2, 0, 1])
Najpierw zamówiono tablicę. Następnie wygeneruj tablicę z początkowym indeksem tablicy.
Po prostu chcę bezpośrednio porównać oryginalne rozumienie OP z rzeczywistą implementacją za pomocą kodu.
numpy.argsort
jest zdefiniowany w taki sposób, że dla tablic 1D:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
OP początkowo uważał, że został zdefiniowany w taki sposób, że dla tablic 1D:
x == numpy.sort(x)[x.argsort()] # this will not be True
Uwaga: ten kod nie działa w ogólnym przypadku (działa tylko dla 1D), ta odpowiedź ma charakter wyłącznie ilustracyjny.
x[x.argsort()]
niekoniecznie jest tym samym, co np.sort(x)
. W rzeczywistości niekoniecznie ma nawet ten sam kształt. Spróbuj tego z tablicą 2D. Dzieje się tak tylko z tablicami 1D.
[3 2 0 1]
byłaby to poprawna odpowiedź?