Perché numpy dà questo risultato:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
quando mi aspetto che lo faccia:
[3 2 0 1]
Chiaramente la mia comprensione della funzione è carente.
Perché numpy dà questo risultato:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
quando mi aspetto che lo faccia:
[3 2 0 1]
Chiaramente la mia comprensione della funzione è carente.
Risposte:
Secondo la documentazione
Restituisce gli indici che ordinerebbero un array.
2
è l'indice di 0.0
.3
è l'indice di 0.1
.1
è l'indice di 1.41
.0
è l'indice di 1.48
.a = x.argsort()
, stampa x[a]
, avremoarray([ 0. , 0.1 , 1.41, 1.48])
[2, 3, 1, 0]
indica che l'elemento più piccolo è all'indice 2, il successivo più piccolo all'indice 3, quindi all'indice 1, quindi all'indice 0.
Esistono diversi modi per ottenere il risultato che stai cercando:
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
Per esempio,
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])
Questo controlla che producano tutti lo stesso risultato:
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))
Questi %timeit
benchmark IPython suggeriscono per array di grandi dimensioni using_indexed_assignment
è il più veloce:
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
Per piccoli array, using_argsort_twice
potrebbe essere più veloce:
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
Nota anche che stats.rankdata
ti dà più controllo su come gestire elementi di uguale valore.
argsort
restituisce gli indici dell'array ordinato. L'indice degli indici ordinati è il rango. Questo è ciò che argsort
restituisce la seconda chiamata a .
Come dice la documentazioneargsort
:
Restituisce gli indici che ordinerebbero un array.
Ciò significa che il primo elemento dell'argsort è l'indice dell'elemento che dovrebbe essere ordinato per primo, il secondo elemento è l'indice dell'elemento che dovrebbe essere il secondo, ecc.
Quello che sembri desiderare è l'ordine di classificazione dei valori, che è ciò che viene fornito da scipy.stats.rankdata
. Nota che devi pensare a cosa dovrebbe accadere se ci sono legami nei ranghi.
numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)
Restituisce gli indici che ordinerebbero un array
Eseguire un ordinamento indiretto lungo l'asse specificato utilizzando l'algoritmo specificato dalla parola chiave kind. Restituisce una matrice di indici della stessa forma dei dati dell'indice lungo l'asse specificato in ordine ordinato.
Considera un esempio in Python, con un elenco di valori come
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Ora usiamo la funzione argsort:
import numpy as np
list(np.argsort(listExample))
L'output sarà
[0, 5, 6, 1, 3, 2, 4]
Questo è l'elenco degli indici dei valori in listExample se si mappano questi indici ai rispettivi valori, otterremo il risultato come segue:
[0, 0, 1, 2, 2000, 2456, 5000]
(Trovo questa funzione molto utile in molti posti, ad esempio se vuoi ordinare l'elenco / array ma non vuoi usare la funzione list.sort () (cioè senza cambiare l'ordine dei valori effettivi nell'elenco) puoi usarlo funzione.)
Per maggiori dettagli fare riferimento a questo link: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
input:
importa numpy come np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()
output:
array ([3, 2, 0, 1])
In primo luogo, è stato ordinato l'array. Quindi genera un array con l'indice iniziale dell'array.
Voglio solo confrontare direttamente la comprensione originale dell'OP con l'effettiva implementazione con il codice.
numpy.argsort
è definito in modo tale che per gli array 1D:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
L'OP inizialmente pensava che fosse definito in modo tale che per gli array 1D:
x == numpy.sort(x)[x.argsort()] # this will not be True
Nota: questo codice non funziona nel caso generale (funziona solo per 1D), questa risposta è puramente a scopo illustrativo.
x[x.argsort()]
non è necessariamente lo stesso di np.sort(x)
. In effetti, non è necessariamente nemmeno la stessa forma. Prova questo con un array 2D. Questo accade solo per funzionare con array 1D.
Restituisce gli indici in base agli indici della matrice data,, [1.48,1.41,0.0,0.1]
ciò significa:
0.0
è il primo elemento, in index [2].
0.1
è il secondo elemento, nell'indice [3].
1.41
è il terzo elemento, nell'indice [1].
1.48
è il quarto elemento, nell'indice [0]. Produzione:
[2,3,1,0]
[3 2 0 1]
sarebbe stata la risposta corretta?