Est-il possible d'utiliser argsort en ordre décroissant

considère le code suivant:

avgDists = np.array([1, 8, 6, 9, 4])
ids = avgDists.argsort()[:n]

cela me donne les indices des plus petits éléments n . Est-il possible d'utiliser ce même argsort dans l'ordre décroissant pour obtenir les indices de n plus d'éléments ?

103
demandé sur wim 2013-05-10 19:57:47

7 réponses

si vous niez un tableau, les éléments les plus bas deviennent les éléments les plus hauts et vice-versa. Par conséquent, les indices des éléments les plus élevés de n sont:

(-avgDists).argsort()[:n]

une autre façon de raisonner à ce sujet, comme mentionné dans le commentaires , est d'observer que les grands éléments viennent dernier dans l'argsort. Ainsi, vous pouvez lire à partir de la queue de l'argsort pour trouver les n éléments les plus élevés:

avgDists.argsort()[::-1][:n]

les deux méthodes sont O(N log n) dans la complexité temporelle, parce que l'appel argsort est le terme dominant ici. Mais la seconde approche a un bel avantage: elle remplace une O(n) négation du réseau par une O(1) tranche. Si vous travaillez avec de petits tableaux à l'intérieur des boucles alors vous pouvez obtenir des gains de performance en évitant cette négation, et si vous travaillez avec des tableaux énormes ensuite, vous pouvez enregistrer sur l'utilisation de la mémoire parce que la négation crée une copie de l'intégralité du tableau.

notez que ces méthodes ne donnent pas toujours des résultats équivalents: si une implémentation de tri stable est demandée à argsort , par exemple en passant le mot-clé argument kind='mergesort' , alors la première stratégie préservera la stabilité de tri, mais la deuxième stratégie cassera la stabilité (c'est-à-dire que les positions des éléments égaux seront inversées).

111
répondu wim 2017-08-06 20:40:04

comme Python, en ce que [::-1] inverse le tableau retourné par argsort() et [:n] donne ce dernier n éléments:

>>> avgDists=np.array([1, 8, 6, 9, 4])
>>> n=3
>>> ids = avgDists.argsort()[::-1][:n]
>>> ids
array([3, 1, 2])

l'avantage de cette méthode est que ids est un vue des avgDists:

>>> ids.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False

(la' donnée propre 'étant fausse indique qu'il s'agit d'une vue et non d'une copie)

une autre façon de faire est quelque chose comme:

(-avgDists).argsort()[:n]

Le problème est que la façon dont cela fonctionne est de créer négatif de chaque élément dans le tableau:

>>> (-avgDists)
array([-1, -8, -6, -9, -4])

et crée une copie pour le faire:

>>> (-avgDists_n).flags['OWNDATA']
True

donc si vous chronométrez chacun, même avec ce très petit ensemble de données:

>>> import timeit
>>> timeit.timeit('(-avgDists).argsort()[:3]', setup="from __main__ import avgDists")
4.2879798610229045
>>> timeit.timeit('avgDists.argsort()[::-1][:3]', setup="from __main__ import avgDists")
2.8372560259886086

Le point de vue de la méthode est beaucoup plus rapide

62
répondu dawg 2014-10-30 14:15:43

Vous pouvez créer une copie du tableau et ensuite multiplier chaque élément avec -1.

En effet, les éléments avant plus grands deviendraient les plus petits.

Les indices des n plus petits éléments de la copie sont les n plus grands éléments de l'original.

3
répondu MentholBonbon 2013-05-10 16:01:38

vous pouvez utiliser les commandes numpy.flipud() ou numpy.fliplr() pour obtenir les index en ordre décroissant après le tri en utilisant la commande argsort . C'est ce que je fais d'habitude.

3
répondu Kanmani 2017-02-24 01:51:52

au lieu d'utiliser np.argsort vous pouvez utiliser np.argpartition - si vous n'avez besoin que des indices des éléments n Les plus bas/les plus élevés.

qui n'a pas besoin de trier le tableau entier, mais juste la partie dont vous avez besoin, mais notez que "l'ordre à l'intérieur de votre partition" n'est pas défini, donc pendant qu'il donne les indices corrects ils pourraient ne pas être correctement ordonnés:

>>> avgDists = [1, 8, 6, 9, 4]
>>> np.array(avgDists).argpartition(2)[:2]  # indices of lowest 2 items
array([0, 4], dtype=int64)

>>> np.array(avgDists).argpartition(-2)[-2:]  # indices of highest 2 items
array([1, 3], dtype=int64)
2
répondu MSeifert 2017-01-19 02:40:25

avec votre exemple:

avgDists = np.array([1, 8, 6, 9, 4])

obtenir les indices de n valeurs maximales:

ids = np.argpartition(avgDists, -n)[-n:]

les Trier par ordre décroissant:

ids = ids[np.argsort(avgDists[ids])[::-1]]

obtenir les résultats (pour n=4):

>>> avgDists[ids]
array([9, 8, 6, 4])
1
répondu Alexey Antonenko 2017-08-21 16:39:26

une autre façon est d'utiliser seulement un '-' dans l'argument pour argsort comme dans : "df[NP.argsort(-df[:, 0])]", à condition que df soit la dataframe et que vous vouliez la Trier par la première colonne (représentée par le numéro de colonne '0'). Modifier la colonne nom approprié. Bien sûr, la colonne doit être un numérique.

0
répondu Biswajit Ghoshal 2017-08-06 14:00:25