165 votes

Numpy argsort - que fait-il ?

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.

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

172voto

falsetru Points 109148

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 .

20 votes

a = x.argsort() , imprimer x[a] nous obtiendrons array([ 0. , 0.1 , 1.41, 1.48])

51voto

unutbu Points 222216

[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.

2 votes

Pouvez-vous expliquer pourquoi le fait d'appliquer deux fois la fonction argsort() nous permet d'obtenir le rang ?

2 votes

@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.

3 votes

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.

4voto

BrenBarn Points 63718

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.

3voto

user9979257 Points 84

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

1voto

JMpony Points 21

L'entrée :
importez numpy comme np
x = np.array([1.48,1.41,0.0,0.1])
x.argsort().argsort()

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

2 votes

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.com

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.

Powered by:

X