Pourquoi numpy donne-t-il ce résultat :
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
alors que je m'attendais à ce qu'il le fasse :
[3 2 0 1]
Il est clair que ma compréhension de la fonction est insuffisante.
Pourquoi numpy donne-t-il ce résultat :
x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()
>[2 3 1 0]
alors que je m'attendais à ce qu'il le fasse :
[3 2 0 1]
Il est clair que ma compréhension de la fonction est insuffisante.
Selon la documentation
Renvoie les indices qui permettraient de trier un tableau.
2
est l'indice de 0.0
.3
est l'indice de 0.1
.1
est l'indice de 1.41
.0
est l'indice de 1.48
.[2, 3, 1, 0]
indique que le plus petit élément est à l'indice 2, le plus petit suivant à l'indice 3, puis à l'indice 1, puis à l'indice 0.
Il y a de plusieurs façons pour obtenir le résultat escompté :
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
Par exemple,
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])
Cela permet de vérifier qu'ils produisent tous le même résultat :
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))
Ces IPython %timeit
Les benchmarks suggèrent pour les grandes matrices using_indexed_assignment
est le plus rapide :
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
Pour les petits réseaux, using_argsort_twice
peut être plus rapide :
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
Notez également que stats.rankdata
vous donne plus de contrôle sur la façon de traiter les éléments de valeur égale.
Pouvez-vous expliquer pourquoi le fait d'appliquer deux fois la fonction argsort() nous permet d'obtenir le rang ?
@Phani : argsort
renvoie les indices du tableau trié. L'indice des indices triés est le rang. C'est ce que le second appel à argsort
les retours.
Le premier argsort renvoie une permutation (qui, appliquée aux données, les trierait). Lorsque argsort est appliqué à (cette permutation ou une autre), il renvoie la permutation inverse (c'est-à-dire que si les deux permutations sont appliquées l'une à l'autre dans n'importe quel ordre, le résultat est l'Identité). La deuxième permutation, si elle est appliquée à un tableau de données trié, produira le tableau de données non trié, c'est-à-dire le rang.
Comme la documentation dit, argsort
:
Renvoie les indices qui permettraient de trier un tableau.
Cela signifie que le premier élément de l'argsort est l'index de l'élément qui doit être trié en premier, le second élément est l'index de l'élément qui doit être en second, etc.
Ce que vous semblez vouloir, c'est l'ordre de classement des valeurs, ce que fournit la fonction scipy.stats.rankdata
. Notez que vous devez penser à ce qui doit se passer s'il y a des liens dans les rangs.
numpy.argsort(a, axis=-1, kind='quicksort', order=None)
Renvoie les indices qui permettraient de trier un tableau
Effectue un tri indirect le long de l'axe donné en utilisant l'algorithme spécifié par le mot clé kind. Elle renvoie un tableau d'indices de la même forme que les données d'indexation le long de l'axe donné, dans l'ordre de tri.
Prenons un exemple en python, avec une liste de valeurs sous la forme de
listExample = [0 , 2, 2456, 2000, 5000, 0, 1]
Maintenant nous utilisons la fonction argsort :
import numpy as np
list(np.argsort(listExample))
La sortie sera
[0, 5, 6, 1, 3, 2, 4]
Il s'agit de la liste des indices des valeurs de listExample. Si vous faites correspondre ces indices aux valeurs respectives, vous obtiendrez le résultat suivant :
[0, 0, 1, 2, 2000, 2456, 5000]
(Je trouve cette fonction très utile dans de nombreux endroits. Par exemple, si vous voulez trier la liste/le tableau mais que vous ne voulez pas utiliser la fonction list.sort() (c'est-à-dire sans changer l'ordre des valeurs réelles dans la liste), vous pouvez utiliser cette fonction).
Pour plus de détails, consultez ce lien : https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html
Bien que cet extrait de code puisse être la solution, y compris une explication contribue réellement à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question pour les lecteurs à venir, et que ces derniers pourraient ne pas connaître les raisons de votre suggestion de code.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
9 votes
Pourquoi avez-vous pensé que
[3 2 0 1]
aurait été la bonne réponse ?12 votes
J'avais simplement une compréhension inversée de la sortie. Par exemple, si vous prenez le premier élément de x, il devrait être en position 3 d'un tableau trié et ainsi de suite.
39 votes
Votre façon de penser est tout à fait logique, j'ai eu exactement la même question
7 votes
[3 2 0 1] - il s'agit d'un classement des valeurs, vous n'obtenez pas les indices réels.
2 votes
Rappelez-vous que la sortie indique les emplacements dans le tableau original alors que vous pensez qu'il s'agit du tableau trié. Cela signifie que output[0] est l'index où se trouve le plus petit élément du tableau d'entrée original et output[-1] pour l'élément le plus grand.
0 votes
Vous avez essayé de les classer, pas de les trier.