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 ?
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).
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
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.
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.
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)
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])
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.