Numpy argsort - que fait-il?

123

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]

quand je m'attendrais à ce qu'il fasse ceci:

[3 2 0 1]

De toute évidence, ma compréhension de la fonction fait défaut.

user1276273
la source
6
Pourquoi pensez-vous que [3 2 0 1]cela aurait été la bonne réponse?
zwol
9
Je viens d'avoir 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.
user1276273
26
votre façon de penser a tout à fait un sens, j'avais exactement la même question
adrienlucca.wordpress.com
2
[3 2 0 1] - il s'agit de classer les valeurs, vous n'obtenez pas les indices réels.
Lahiru Karunaratne
Rappelez-vous simplement que la sortie indique des emplacements dans le tableau d'origine alors que vous le pensez dans le tableau trié. Cela signifie que la sortie [0] est l'index où le plus petit élément du tableau d'entrée d'origine localise et la sortie [-1] pour le plus grand élément.
lincr

Réponses:

144

Selon la documentation

Renvoie les indices qui trieraient un tableau.

  • 2est l'indice de 0.0.
  • 3est l'indice de 0.1.
  • 1est l'indice de 1.41.
  • 0est l'indice de 1.48.
falsetru
la source
12
a = x.argsort(), imprimer x[a], nous obtiendronsarray([ 0. , 0.1 , 1.41, 1.48])
Belter
39

[2, 3, 1, 0] indique que le plus petit élément est à l'index 2, le plus petit suivant à l'index 3, puis l'index 1, puis l'index 0.

Il existe plusieurs façons d'obtenir le résultat que vous recherchez:

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 vérifie 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 %timeitbenchmarks IPython suggèrent que pour les grands tableaux, using_indexed_assignmentc'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 tableaux, using_argsort_twicepeut ê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 cela stats.rankdatavous donne plus de contrôle sur la façon de gérer les éléments de valeur égale.

unutbu
la source
1
Pouvez-vous ajouter quelques explications sur la raison pour laquelle appliquer argsort () deux fois nous donne le rang?
Phani
1
@Phani: argsortretourne les indices du tableau trié. L'index des indices triés est le rang. C'est ce que argsortretourne le deuxième appel .
unutbu
2
Le premier tri d'arguments renvoie une permutation (qui, si elle était appliquée aux données, les trierait). Lorsque argsort est appliqué à (telle ou telle) permutation, il renvoie la permutation inverse (que si les 2 permutations sont appliquées l'une à l'autre dans l'un ou l'autre ordre, le résultat est l'identité). La deuxième permutation, si elle est appliquée à un tableau de données triées, produirait le tableau de données non triées, c'est-à-dire qu'il s'agit du rang.
Alex C
1
L'esprit soufflé. J'ai enfin compris! Il retourne un tableau dont le contenu correspond aux indices du tableau d'origine dans un ordre trié.
Jose A
3

Comme la documentation dit argsort:

Renvoie les indices qui trieraient un tableau.

Cela signifie que le premier élément de argsort est l'index de l'élément qui doit être trié en premier, le deuxième élément est l'index de l'élément qui devrait être le deuxième, etc.

Ce que vous semblez vouloir, c'est l'ordre de classement des valeurs, qui est fourni par scipy.stats.rankdata. Notez que vous devez réfléchir à ce qui devrait se passer s'il y a des liens dans les rangs.

BrenBarn
la source
3

numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)

Renvoie les indices qui trieraient un tableau

Effectuez un tri indirect le long de l'axe donné en utilisant l'algorithme spécifié par le mot-clé kind. Il renvoie un tableau d'indices de la même forme que ces données d'index le long de l'axe donné dans l'ordre trié.

Prenons un exemple en python, ayant une liste de valeurs comme

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]

Voici la liste des indices de valeurs dans listExample si vous mappez ces indices aux valeurs respectives, nous obtiendrons le résultat comme suit:

[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 ne voulez pas utiliser la fonction list.sort () (c'est-à-dire sans changer l'ordre des valeurs réelles dans la liste), vous pouvez l'utiliser fonction.)

Pour plus de détails, référez-vous à ce lien: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html

Yogesh
la source
1

input:
import numpy as np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()

sortie:
tableau ([3, 2, 0, 1])

JMpony
la source
1
Bien que cet extrait de code puisse être la solution, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
peacetype
0

Tout d'abord, il a été commandé le tableau. Générez ensuite un tableau avec l'index initial du tableau.

Rodrigo Saraguro
la source
0

np.argsort renvoie l'index du tableau trié donné par le 'kind' (qui spécifie le type d'algorithme de tri). Cependant, lorsqu'une liste est utilisée avec np.argmax, elle renvoie l'index du plus grand élément de la liste. Alors que, np.sort, trie le tableau donné, list.

vivek
la source
0

Je veux juste comparer directement la compréhension originale du PO avec l'implémentation réelle avec du code.

numpy.argsort est défini de telle sorte que pour les tableaux 1D:

x[x.argsort()] == numpy.sort(x) # this will be an array of True's

L'OP pensait à l'origine qu'il était défini de telle sorte que pour les tableaux 1D:

x == numpy.sort(x)[x.argsort()] # this will not be True

Remarque: ce code ne fonctionne pas dans le cas général (ne fonctionne que pour 1D), cette réponse est purement à des fins d'illustration.

Multihunter
la source
x[x.argsort()]n'est pas nécessairement le même que np.sort(x). En fait, ce n'est même pas nécessairement la même forme. Essayez ceci avec un tableau 2D. Cela ne fonctionne qu'avec des baies 1D.
Nathan
J'ai l'impression que c'est inutilement pédant. La question concerne les tableaux 1D. C'est un moyen de comprendre quelle était la différence, plutôt que du code littéral à utiliser. De plus, lorsque vous avez un tableau 2D, le type de tri souhaité n'est même pas clair. Voulez-vous un tri global? Sinon, quel axe doit être trié? Quoi qu'il en soit, j'ai ajouté un avertissement.
Multihunter
0

Il renvoie des indices en fonction des indices de tableau donnés,, [1.48,1.41,0.0,0.1]c'est-à-dire: 0.0est le premier élément, dans l'index [2]. 0.1est le deuxième élément, dans l'index [3]. 1.41est le troisième élément, dans l'index [1]. 1.48est le quatrième élément, dans l'index [0]. Production:

[2,3,1,0]
nucsit026
la source