¿Por qué numpy está dando este resultado?
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
cuando esperaría que hiciera esto:
[3 2 0 1]
Claramente, mi comprensión de la función es deficiente.
¿Por qué numpy está dando este resultado?
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
cuando esperaría que hiciera esto:
[3 2 0 1]
Claramente, mi comprensión de la función es deficiente.
Respuestas:
Según la documentación
Devuelve los índices que ordenarían una matriz.
2es el índice de 0.0.3es el índice de 0.1.1es el índice de 1.41.0es el índice de 1.48.a = x.argsort(), imprimir x[a], obtendremosarray([ 0. , 0.1 , 1.41, 1.48])
[2, 3, 1, 0] indica que el elemento más pequeño está en el índice 2, el siguiente más pequeño en el índice 3, luego el índice 1, luego el índice 0.
Hay varias formas de obtener el resultado que busca:
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
Por ejemplo,
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])
Esto verifica que todos produzcan el mismo resultado:
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))
Estos %timeitpuntos de referencia de IPython sugieren que para arreglos grandes using_indexed_assignmentes el más rápido:
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
Para arreglos pequeños, using_argsort_twicepuede ser más rápido:
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
Tenga en cuenta también que stats.rankdatale da más control sobre cómo manejar elementos de igual valor.
argsortdevuelve los índices de la matriz ordenada. El índice de los índices ordenados es el rango. Esto es lo que argsortvuelve la segunda llamada a .
Como dice la documentaciónargsort :
Devuelve los índices que ordenarían una matriz.
Eso significa que el primer elemento del argsort es el índice del elemento que debe ordenarse primero, el segundo elemento es el índice del elemento que debe ser el segundo, etc.
Lo que parece querer es el orden de clasificación de los valores, que es lo que proporciona scipy.stats.rankdata. Tenga en cuenta que debe pensar en lo que debería suceder si hay empates en las filas.
numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)
Devuelve los índices que ordenarían una matriz.
Realice una ordenación indirecta a lo largo del eje dado utilizando el algoritmo especificado por la palabra clave kind. Devuelve una matriz de índices de la misma forma que los datos del índice a lo largo del eje dado en orden ordenado.
Considere un ejemplo en Python, que tiene una lista de valores como
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Ahora usamos la función argsort:
import numpy as np
list(np.argsort(listExample))
La salida será
[0, 5, 6, 1, 3, 2, 4]
Esta es la lista de índices de valores en listEjemplo, si asigna estos índices a los valores respectivos, obtendremos el resultado de la siguiente manera:
[0, 0, 1, 2, 2000, 2456, 5000]
(Encuentro esta función muy útil en muchos lugares, por ejemplo, si desea ordenar la lista / matriz pero no desea usar la función list.sort () (es decir, sin cambiar el orden de los valores reales en la lista) puede usar esto función.)
Para obtener más detalles, consulte este enlace: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
entrada:
importar numpy como np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()
salida:
matriz ([3, 2, 0, 1])
Primero, se ordenó la matriz. Luego genere una matriz con el índice inicial de la matriz.
Solo quiero contrastar directamente la comprensión original del OP con la implementación real con código.
numpy.argsort se define de modo que para matrices 1D:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
El OP originalmente pensó que estaba definido de tal manera que para matrices 1D:
x == numpy.sort(x)[x.argsort()] # this will not be True
Nota: Este código no funciona en el caso general (solo funciona para 1D), esta respuesta es puramente ilustrativa.
x[x.argsort()]no es necesariamente lo mismo que np.sort(x). De hecho, ni siquiera tiene necesariamente la misma forma. Pruebe esto con una matriz 2D. Esto solo funciona con matrices 1D.
Devuelve índices de acuerdo con los índices de matriz dados [1.48,1.41,0.0,0.1], eso significa:
0.0es el primer elemento, en index [2].
0.1es el segundo elemento, en el índice [3].
1.41es el tercer elemento, en el índice [1].
1.48es el cuarto elemento, en el índice [0]. Salida:
[2,3,1,0]
[3 2 0 1]que habría sido la respuesta correcta?