NumPy propose un moyen d'obtenir l'index de la valeur maximale d'un tableau via np.argmax
.
Je voudrais une chose similaire, mais en retournant les index des N
valeurs maximales.
Par exemple, si j'ai un tableau, [1, 3, 2, 4, 5]
, function(array, n=3)
renverrait les indices [4, 3, 1]
qui correspondent aux éléments [5, 4, 3]
.
python
numpy
max
numpy-ndarray
Alexis Métaireau
la source
la source
array([5, 1, 5, 5, 2, 3, 2, 4, 1, 5])
Whit,n= 3
? Lequel de toutes les alternatives, comme[0, 2, 3]
,[0, 2, 9]
,...
serait la bonne? Veuillez élaborer davantage sur vos besoins spécifiques. Merciargsort
pourrait être une alternative viable si vous ne vous souciez pas de l'ordre des indécis retournés. Voir ma réponse ci-dessous.Réponses:
Le plus simple que j'ai pu trouver est:
Cela implique une sorte complète de tableau. Je me demande si
numpy
fournit un moyen intégré de faire un tri partiel; jusqu'à présent, je n'ai pas pu en trouver un.Si cette solution s'avère trop lente (en particulier pour les petits
n
), il peut être utile de regarder quelque chose de coder en Cython .la source
arr.argsort()[-1:-4:-1]
? Je l'ai essayé dans l'interpréteur et cela donne le même résultat, mais je me demande si ce n'est pas cassé par un exemple.np.argsort(-arr)[:3]
, que je trouve plus lisible et pertinent.arr.argsort()[::-1][:n]
est mieux car il renvoie vide pourn=0
au lieu du tableau completLes versions plus récentes de NumPy (1.8 et plus) ont une fonction appelée
argpartition
à cet effet. Pour obtenir les indices des quatre plus grands éléments, faitesContrairement à
argsort
, cette fonction s'exécute en temps linéaire dans le pire des cas, mais les indices renvoyés ne sont pas triés, comme le montre le résultat de l'évaluationa[ind]
. Si vous en avez également besoin, triez-les ensuite:Pour obtenir le top- k éléments l' ordre de tri de cette manière prend O ( n + k log k ) temps.
la source
argpartition
s'exécute en temps linéaire, O (n), en utilisant l' algorithme introsélection . Le tri suivant ne gère que k éléments, de sorte que s'exécute dans O (k log k).np.argpartition
et son algorithme sœur,np.partition
il y a une explication plus détaillée dans la question liée: stackoverflow.com/questions/10337533/…a=np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
parce que les listes python normales ne prennent pas en charge l'indexation par listes, contrairement ànp.array
np.argpartition
prend unaxis
argument facultatif . Pour trouver les indices des n premières valeurs pour chaque ligne:np.argpartition(a, -n, axis=1)[-n:]
Plus simple encore:
où n est le nombre de valeurs maximales.
la source
arr[arr.argsort()[-n:]]
au lieu de nier le tableau, prenez simplement une tranche des n derniers élémentsUtilisation:
Pour les listes Python régulières:
Si vous utilisez Python 2, utilisez
xrange
plutôt querange
.Source: heapq - Algorithme de file d'attente de tas
la source
heapq.nlargest(3, xrange(len(a)), a.take)
. Pour les listes Python, nous pouvons utiliser à la.__getitem__
place de.take
.A
en général:heapq.nlargest(3, range(len(A.ravel())), A.ravel().take)
. (J'espère que cela ne fonctionne que sur les vues, voir aussi (ravel vs flatten
] ( stackoverflow.com/a/28930580/603003 )).Si vous travaillez avec un tableau multidimensionnel, vous devrez aplatir et démêler les indices:
Par exemple:
la source
Si vous ne vous souciez pas de l' ordre des K-ème éléments les plus grands que vous pouvez utiliser
argpartition
, qui devraient être plus performants qu'un tri completargsort
.Les crédits vont à cette question .
J'ai effectué quelques tests et cela ressemble à des
argpartition
performances supérieures àargsort
mesure que la taille du tableau et la valeur de K augmentent.la source
Pour les tableaux multidimensionnels, vous pouvez utiliser le
axis
mot - clé afin d'appliquer le partitionnement le long de l'axe attendu.Et pour saisir les objets:
Mais notez que cela ne retournera pas un résultat trié. Dans ce cas, vous pouvez utiliser le
np.argsort()
long de l'axe prévu:Voici un exemple:
la source
np.take_along_axis
(qui n'existait probablement pas lorsque vous avez répondu à cette question)Ce sera plus rapide qu'un tri complet selon la taille de votre tableau d'origine et la taille de votre sélection:
Cela implique, bien entendu, de falsifier votre baie d'origine. Que vous pourriez corriger (si nécessaire) en faisant une copie ou en remplaçant les valeurs d'origine. ... selon ce qui est le moins cher pour votre cas d'utilisation.
la source
argmax(.)
sans ambiguïté. (À mon humble avis, il essaie de suivre une sorte de logique de court-circuit, mais ne parvient malheureusement pas à fournir un comportement universellement acceptable). MerciLa méthode
np.argpartition
ne renvoie que les k plus grands indices, effectue un tri local et est plus rapide quenp.argsort
(effectuer un tri complet) lorsque le tableau est assez grand. Mais les indices retournés ne sont PAS dans l'ordre croissant / décroissant . Disons avec un exemple:Nous pouvons voir que si vous voulez un ordre k croissant, les meilleurs index
np.argpartition
ne retourneront pas ce que vous voulez.En plus de faire un tri manuellement après np.argpartition, ma solution est d'utiliser PyTorch,
torch.topk
un outil pour la construction de réseaux neuronaux, fournissant des API de type NumPy avec prise en charge CPU et GPU. Il est aussi rapide que NumPy avec MKL et offre un boost GPU si vous avez besoin de grands calculs matriciels / vectoriels.Le code strict des k premiers indices ascendants / descendants sera:
Notez qu'il
torch.topk
accepte un tenseur de torche et renvoie à la fois les k premières valeurs et les k premiers indices en typetorch.Tensor
. Similaire à np, torch.topk accepte également un argument d'axe afin que vous puissiez gérer des tableaux / tenseurs multidimensionnels.la source
Utilisation:
Maintenant, la
result
liste contiendrait N tuples (index
,value
) oùvalue
est maximisé.la source
Utilisation:
Il fonctionne également avec des tableaux 2D. Par exemple,
la source
bottleneck
a une fonction de tri partiel, si le coût du tri du tableau entier juste pour obtenir les N valeurs les plus grandes est trop grand.Je ne sais rien de ce module; Je viens de googler
numpy partial sort
.la source
Ce qui suit est un moyen très simple de voir le maximum d'éléments et ses positions. Voici
axis
le domaine;axis
= 0 signifie le nombre maximum par colonne etaxis
= 1 signifie le nombre maximum par ligne pour le cas 2D. Et pour des dimensions supérieures, cela dépend de vous.la source
Je l'ai trouvé le plus intuitif à utiliser
np.unique
.L'idée est que la méthode unique renvoie les indices des valeurs d'entrée. Ensuite, à partir de la valeur unique maximale et des indices, la position des valeurs d'origine peut être recréée.
la source
Je pense que le moyen le plus efficace en termes de temps est d'itérer manuellement le tableau et de conserver un min-tas de taille k, comme d'autres l'ont mentionné.
Et je propose également une approche par force brute:
Définissez le plus grand élément sur une grande valeur négative après avoir utilisé argmax pour obtenir son index. Et puis le prochain appel d'argmax retournera le deuxième plus grand élément. Et vous pouvez enregistrer la valeur d'origine de ces éléments et les récupérer si vous le souhaitez.
la source
Ce code fonctionne pour un tableau matriciel numpy:
Cela produit une indexation matricielle n_largest vraie-fausse qui fonctionne également pour extraire les éléments n_largest d'un tableau matriciel
la source