183 votes

Trouver le nombre le plus fréquent dans un tableau NumPy

Supposons que j'ai le tableau NumPy suivant :

a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])

Comment puis-je trouver le nombre le plus fréquent dans ce tableau ?

0 votes

250voto

JoshAdel Points 15911

Si votre liste contient tous les ints non-négatifs, vous devriez jeter un coup d'œil à numpy.bincounts :

http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html

et ensuite probablement utiliser np.argmax :

a = np.array([1,2,3,1,2,1,1,1,3,2,2,1])
counts = np.bincount(a)
print(np.argmax(counts))

Pour une liste plus compliquée (qui contient peut-être des nombres négatifs ou des valeurs non entières), vous pouvez utiliser np.histogram de la même manière. Sinon, si vous voulez simplement travailler en python sans utiliser numpy, collections.Counter est un bon moyen de traiter ce type de données.

from collections import Counter
a = [1,2,3,1,2,1,1,1,3,2,2,1]
b = Counter(a)
print(b.most_common(1))

70 votes

+1. Ça pourrait être juste np.bincount([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1]).argmax()

1 votes

+1. C'est au moins un ordre de grandeur plus rapide que scipy.stats.mode bien que moins général.

0 votes

Bonne réponse ! Cependant, si quelqu'un est sur python 2.6, collections.Counter n'est pas disponible. Dans ce cas, voir ma réponse ci-dessous.

139voto

Apogentus Points 170

Vous pouvez utiliser

 values, counts = np.unique(a, return_counts=True)

ind = np.argmax(counts)
print(values[ind])  # prints the most frequent element

ind = np.argpartition(-counts, kth=10)[:10]
print(values[ind])  # prints the 10 most frequent elements

Si un élément est aussi fréquent qu'un autre, ce code ne retournera que le premier élément.

9 votes

Je trouve que c'est le plus utile car il est générique, court et permet de tirer des éléments de valeurs ou de comptes par un indice dérivé.

7 votes

Si nous avons plusieurs valeurs les plus fréquentes, values[counts.argmax()] retournera la première valeur. Pour les obtenir toutes, nous pouvons utiliser values[counts == counts.max()] .

54voto

larsmans Points 167484

Si vous êtes prêt à utiliser SciPy :

 >>> from scipy.stats import mode
>>> mode([1,2,3,1,2,1,1,1,3,2,2,1])
(array([ 1.]), array([ 6.]))
>>> most_frequent = mode([1,2,3,1,2,1,1,1,3,2,2,1])[0][0]
>>> most_frequent
1.0

36voto

iuridiniz Points 1667

Performances (en utilisant iPython) pour certaines solutions trouvées ici :

>>> # small array
>>> a = [12,3,65,33,12,3,123,888000]
>>> 
>>> import collections
>>> collections.Counter(a).most_common()[0][0]
3
>>> %timeit collections.Counter(a).most_common()[0][0]
100000 loops, best of 3: 11.3 µs per loop
>>> 
>>> import numpy
>>> numpy.bincount(a).argmax()
3
>>> %timeit numpy.bincount(a).argmax()
100 loops, best of 3: 2.84 ms per loop
>>> 
>>> import scipy.stats
>>> scipy.stats.mode(a)[0][0]
3.0
>>> %timeit scipy.stats.mode(a)[0][0]
10000 loops, best of 3: 172 µs per loop
>>> 
>>> from collections import defaultdict
>>> def jjc(l):
...     d = defaultdict(int)
...     for i in a:
...         d[i] += 1
...     return sorted(d.iteritems(), key=lambda x: x[1], reverse=True)[0]
... 
>>> jjc(a)[0]
3
>>> %timeit jjc(a)[0]
100000 loops, best of 3: 5.58 µs per loop
>>> 
>>> max(map(lambda val: (a.count(val), val), set(a)))[1]
12
>>> %timeit max(map(lambda val: (a.count(val), val), set(a)))[1]
100000 loops, best of 3: 4.11 µs per loop
>>> 

Le meilleur est "max" avec "set". pour les petits tableaux comme le problème.

Selon @David Sanders, si vous augmentez la taille du tableau à quelque chose comme 100 000 éléments, l'algorithme "max w/set" finit par étant de loin le pire alors que la méthode "numpy bincount" est la meilleure.

1 votes

@IuliusCurt afin de déterminer la meilleure approche, nous devons la tester dans plusieurs cas : petits tableaux, grands tableaux, tableaux aléatoires, tableaux du monde réel (par exemple timsort fait pour le tri), ... Mais je suis d'accord avec vous

4 votes

L'utilisation d'un petit tableau, comme c'est le cas dans votre approche, ne permet pas de faire une distinction très nette entre les différents algorithmes.

12 votes

Si vous augmentez la taille de la liste de test à 100000 ( a = (np.random.rand(100000) * 1000).round().astype('int'); a_list = list(a) ), votre algorithme "max w/set" s'avère être de loin le pire alors que la méthode "numpy bincount" est la meilleure. J'ai effectué ce test en utilisant a_list pour le code python natif et a pour le code numpy afin d'éviter que les coûts de marshalling n'altèrent les résultats.

9voto

Xavier Guihot Points 6414

À partir de Python 3.4 la bibliothèque standard comprend la fonction statistics.mode pour renvoyer le point de données le plus courant.

from statistics import mode

mode([1, 2, 3, 1, 2, 1, 1, 1, 3, 2, 2, 1])
# 1

S'il y a plusieurs modes avec la même fréquence, statistics.mode renvoie le premier rencontré.


À partir de Python 3.8 le statistics.multimode renvoie une liste des valeurs les plus fréquentes dans l'ordre où elles ont été rencontrées pour la première fois :

from statistics import multimode

multimode([1, 2, 3, 1, 2])
# [1, 2]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X