Si vous annulez un tableau, les éléments les plus bas deviennent les éléments les plus élevés et vice-versa. Par conséquent, les indices des n
éléments les plus élevés sont:
(-avgDists).argsort()[:n]
Une autre façon de raisonner à ce sujet, comme mentionné dans les commentaires , est d'observer que les gros éléments arrivent en dernier dans l'argsort. Ainsi, vous pouvez lire à partir de la queue de l'argument pour trouver les n
éléments les plus élevés:
avgDists.argsort()[::-1][:n]
Les deux méthodes sont O (n log n) en complexité temporelle, car l' argsort
appel est ici le terme dominant. Mais la seconde approche a un bel avantage: elle remplace une négation O (n) du tableau par un O (1) tranche . Si vous travaillez avec de petits tableaux à l'intérieur de boucles, vous pouvez obtenir des gains de performances en évitant cette négation, et si vous travaillez avec d'énormes tableaux, vous pouvez économiser sur l'utilisation de la mémoire car la négation crée une copie de l'ensemble 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 l'argument mot-clé kind='mergesort'
, alors la première stratégie préservera la stabilité du tri, mais la deuxième stratégie cassera la stabilité (c'est-à-dire les positions égales les éléments seront inversés).
Exemple d'horaires:
En utilisant un petit tableau de 100 flotteurs et une longueur de 30 queue, la méthode de visualisation était environ 15% plus rapide
>>> avgDists = np.random.rand(100)
>>> n = 30
>>> timeit (-avgDists).argsort()[:n]
1.93 µs ± 6.68 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
1.64 µs ± 3.39 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
1.64 µs ± 3.66 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Pour les tableaux plus grands, le tri d'argument est dominant et il n'y a pas de différence de temps significative
>>> avgDists = np.random.rand(1000)
>>> n = 300
>>> timeit (-avgDists).argsort()[:n]
21.9 µs ± 51.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[::-1][:n]
21.7 µs ± 33.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> timeit avgDists.argsort()[-n:][::-1]
21.9 µs ± 37.1 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Veuillez noter que le commentaire de nedim ci-dessous est incorrect. Le fait de tronquer avant ou après l'inversion ne fait aucune différence en termes d'efficacité, car ces deux opérations ne font que parcourir différemment une vue du tableau et ne copient pas réellement les données.
ids = np.array(avgDists).argsort()[-n:]
?