web-dev-qa-db-fra.com

Trier efficacement un tableau numpy par ordre décroissant?

Je suis surpris que cette question spécifique n'ait pas été posée auparavant, mais je ne l'ai vraiment pas trouvée dans SO, ni dans la documentation de np.sort.

Disons que j'ai un tableau numpy aléatoire contenant des entiers, par exemple:

> temp = np.random.randint(1,10, 10)    
> temp
array([2, 4, 7, 4, 2, 2, 7, 6, 4, 4])

Si je le trie, j'obtiens un ordre croissant par défaut:

> np.sort(temp)
array([2, 2, 2, 4, 4, 4, 4, 6, 7, 7])

mais je veux que la solution soit triée dans l'ordre décroissant.

Maintenant, je sais que je peux toujours faire:

reverse_order = np.sort(temp)[::-1]

mais est-ce que cette dernière déclaration est efficace? Ne crée-t-il pas une copie dans l'ordre croissant, puis l'inverse pour obtenir le résultat dans l'ordre inverse? Si tel est effectivement le cas, existe-t-il une alternative efficace? Il ne semble pas que np.sort accepte les paramètres permettant de modifier le signe des comparaisons dans l'opération de tri pour obtenir les éléments dans l'ordre inverse.

84

temp[::-1].sort() trie le tableau en place, alors que np.sort(temp)[::-1] crée un nouveau tableau.

In [25]: temp = np.random.randint(1,10, 10)

In [26]: temp
Out[26]: array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

In [27]: id(temp)
Out[27]: 139962713524944

In [28]: temp[::-1].sort()

In [29]: temp
Out[29]: array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

In [30]: id(temp)
Out[30]: 139962713524944
103
Padraic Cunningham
>>> a=np.array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

>>> np.sort(a)
array([2, 2, 4, 4, 4, 4, 5, 6, 7, 8])

>>> -np.sort(-a)
array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])
63
Mike O'Connor

Pour les tableaux courts, je suggère d'utiliser np.argsort() en recherchant les indices du tableau trié négatif, ce qui est légèrement plus rapide que l'inversion du tableau trié:

In [37]: temp = np.random.randint(1,10, 10)

In [38]: %timeit np.sort(temp)[::-1]
100000 loops, best of 3: 4.65 µs per loop

In [39]: %timeit temp[np.argsort(-temp)]
100000 loops, best of 3: 3.91 µs per loop
13
Kasrâmvd

Malheureusement, lorsque vous avez un tableau complexe, seul np.sort(temp)[::-1] fonctionne correctement. Les deux autres méthodes mentionnées ici ne sont pas efficaces.

6
anishtain4

Bonjour, je cherchais une solution de tri inversé d’un tableau numpy bidimensionnel, et je n’ai rien trouvé qui puisse fonctionner, mais je pense être tombé sur une solution que j’ajoute au cas où quelqu'un se retrouverait dans le même bateau.

x=np.sort(array)
y=np.fliplr(x)

np.sort trie par ordre croissant ce qui n'est pas ce que vous voulez, mais la commande fliplr retourne les lignes de gauche à droite! Semble travailler!

J'espère que ça vous aide!

Je suppose que cela ressemble à la suggestion à propos de -np.sort (-a) ci-dessus, mais j'ai été rebuté par ce commentaire en disant que cela ne fonctionne pas toujours. Peut-être que ma solution ne fonctionnera pas toujours non plus, mais je l’ai testée avec quelques tableaux et elle semble bien fonctionner.

3
Naz

Faites attention aux dimensions.

Laisser

_x  # initial numpy array
I = np.argsort(x) or I = x.argsort() 
y = np.sort(x)    or y = x.sort()
z  # reverse sorted array
_

Inversion complète

_z = x[-I]
z = -np.sort(-x)
z = np.flip(y)
_
  • flip modifié en 1.15 , versions précédentes 1.14 requis axis. Solution: _pip install --upgrade numpy_.

Première dimension inversée

_z = y[::-1]
z = np.flipud(y)
z = np.flip(y, axis=0)
_

Deuxième dimension inversée

_z = y[::-1, :]
z = np.fliplr(y)
z = np.flip(y, axis=1)
_

Essai

Test sur une matrice 100 × 10 × 10 1000 fois.

_Method       | Time (ms)
-------------+----------
y[::-1]      | 0.126659  # only in first dimension
-np.sort(-x) | 0.133152
np.flip(y)   | 0.121711
x[-I]        | 4.611778

x.sort()     | 0.024961
x.argsort()  | 0.041830
np.flip(x)   | 0.002026
_

Ceci est principalement dû à la réindexation plutôt qu'à argsort.

_# Timing code
import time
import numpy as np


def timeit(fun, xs):
    t = time.time()
    for i in range(len(xs)):  # inline and map gave much worse results for x[-I], 5*t
        fun(xs[i])
    t = time.time() - t
    print(np.round(t,6))

I, N = 1000, (100, 10, 10)
xs = np.random.Rand(I,*N)
timeit(lambda x: np.sort(x)[::-1], xs)
timeit(lambda x: -np.sort(-x), xs)
timeit(lambda x: np.flip(x.sort()), xs)
timeit(lambda x: x[-x.argsort()], xs)
timeit(lambda x: x.sort(), xs)
timeit(lambda x: x.argsort(), xs)
timeit(lambda x: np.flip(x), xs)
_
0
A. West

je suggère d'utiliser ceci ...

np.arange(start_index, end_index, intervals)[::-1]

par exemple:

np.arange(10, 20, 0.5)
np.arange(10, 20, 0.5)[::-1]

Alors votre resault:

[ 19.5,  19. ,  18.5,  18. ,  17.5,  17. ,  16.5,  16. ,  15.5,
    15. ,  14.5,  14. ,  13.5,  13. ,  12.5,  12. ,  11.5,  11. ,
    10.5,  10. ]
0
morteza omidipoor