Por que o numpy está dando esse resultado:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
quando eu esperava fazer isso:
[3 2 0 1]
Claramente, falta minha compreensão da função.
Por que o numpy está dando esse resultado:
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
quando eu esperava fazer isso:
[3 2 0 1]
Claramente, falta minha compreensão da função.
Respostas:
De acordo com a documentação
Retorna os índices que ordenariam uma matriz.
2
é o índice de 0.0
.3
é o índice de 0.1
.1
é o índice de 1.41
.0
é o índice de 1.48
.a = x.argsort()
, Imprimir x[a]
, teremosarray([ 0. , 0.1 , 1.41, 1.48])
[2, 3, 1, 0]
indica que o menor elemento está no índice 2, o menor menor no índice 3, depois no índice 1 e depois no índice 0.
Existem várias maneiras de obter o resultado que você está procurando:
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 exemplo,
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])
Isso verifica se todos eles produzem o mesmo 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))
Esses %timeit
benchmarks IPython sugerem que para grandes matrizes using_indexed_assignment
é o mais 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 matrizes pequenas, using_argsort_twice
pode ser mais 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
Observe também que stats.rankdata
você oferece mais controle sobre como lidar com elementos de igual valor.
argsort
retorna os índices da matriz classificada. O índice dos índices classificados é a classificação. É para isso que a segunda chamada argsort
retorna.
Como a documentação diz argsort
:
Retorna os índices que ordenariam uma matriz.
Isso significa que o primeiro elemento do argsort é o índice do elemento que deve ser classificado primeiro, o segundo elemento é o índice do elemento que deve ser o segundo, etc.
O que você parece querer é a ordem de classificação dos valores, que é fornecida por scipy.stats.rankdata
. Observe que você precisa pensar no que deve acontecer se houver laços nas fileiras.
numpy.argsort (a, eixo = -1, tipo = 'classificação rápida', ordem = Nenhuma)
Retorna os índices que ordenariam uma matriz
Execute uma classificação indireta ao longo do eixo especificado, usando o algoritmo especificado pela palavra-chave kind. Ele retorna uma matriz de índices da mesma forma que os dados do índice ao longo do eixo especificado em ordem classificada.
Considere um exemplo em python, com uma lista de valores como
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Agora usamos a função argsort:
import numpy as np
list(np.argsort(listExample))
A saída será
[0, 5, 6, 1, 3, 2, 4]
Esta é a lista de índices de valores em listExample, se você mapear esses índices para os respectivos valores, obteremos o resultado da seguinte forma:
[0, 0, 1, 2, 2000, 2456, 5000]
(Eu acho essa função muito útil em muitos lugares, por exemplo, se você deseja classificar a lista / matriz, mas não deseja usar a função list.sort () (ou seja, sem alterar a ordem dos valores reais na lista), você pode usar isso função.)
Para obter mais detalhes, consulte este link: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
input:
import numpy como np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()
saída:
matriz ([3, 2, 0, 1])
Primeiro, foi ordenada a matriz. Em seguida, gere uma matriz com o índice inicial da matriz.
Só quero contrastar diretamente o entendimento original do OP em relação à implementação real com o código.
numpy.argsort
é definido de modo que, para matrizes 1D:
x[x.argsort()] == numpy.sort(x) # this will be an array of True's
O OP originalmente pensava que estava definido de tal forma que, para as matrizes 1D:
x == numpy.sort(x)[x.argsort()] # this will not be True
Nota: Este código não funciona no caso geral (funciona apenas para 1D), esta resposta é meramente ilustrativa.
x[x.argsort()]
não é necessariamente o mesmo que np.sort(x)
. Na verdade, não é necessariamente nem a mesma forma. Tente isso com uma matriz 2D. Isso acontece apenas com matrizes 1D.
[3 2 0 1]
que teria sido a resposta correta?