Étant donné un élément, comment puis-je compter ses occurrences dans une liste en Python?
Si vous ne voulez compter que le nombre d'un élément, utilisez la méthode count
:
>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3
Ne pas utilisez ceci si vous voulez compter plusieurs éléments. L'appel de count
dans une boucle nécessite un passage distinct sur la liste pour chaque appel count
, ce qui peut être catastrophique pour la performance. Si vous souhaitez compter tous les éléments, ou même plusieurs éléments, utilisez Counter
, comme expliqué dans les autres réponses.
Si vous utilisez Python 2.7 ou 3 et que vous souhaitez un nombre d'occurrences pour chaque élément:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
Comptage des occurrences d'un élément dans une liste
Pour compter les occurrences d'un seul élément de la liste, vous pouvez utiliser count()
>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2
Compter les occurrences de tous éléments dans une liste est également appelé "décompter" une liste ou créer un compteur de décompte.
Compter tous les éléments avec count ()
Pour compter les occurrences d'éléments dans l
, on peut simplement utiliser une compréhension de liste et la méthode count()
[[x,l.count(x)] for x in set(l)]
(ou similaire avec un dictionnaire dict((x,l.count(x)) for x in set(l))
)
Exemple:
>>> l = ["a","b","b"]
>>> [[x,l.count(x)] for x in set(l)]
[['a', 1], ['b', 2]]
>>> dict((x,l.count(x)) for x in set(l))
{'a': 1, 'b': 2}
Compter tous les éléments avec Counter ()
Sinon, il y a la classe Counter
plus rapide de la bibliothèque collections
Counter(l)
Exemple:
>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})
Combien est plus rapide Counter?
J'ai vérifié combien Counter
est beaucoup plus rapide pour compiler des listes. J'ai essayé les deux méthodes avec quelques valeurs de n
et il semble que Counter
soit plus rapide d'un facteur constant d'environ 2.
Voici le script que j'ai utilisé:
from __future__ import print_function
import timeit
t1=timeit.Timer('Counter(l)', \
'import random;import string;from collections import Counter;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
t2=timeit.Timer('[[x,l.count(x)] for x in set(l)]',
'import random;import string;n=1000;l=[random.choice(string.ascii_letters) for x in range(n)]'
)
print("Counter(): ", t1.repeat(repeat=3,number=10000))
print("count(): ", t2.repeat(repeat=3,number=10000)
Et la sortie:
Counter(): [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count(): [7.779430688009597, 7.962715800967999, 8.420845870045014]
Une autre façon d’obtenir le nombre d’occurrences de chaque élément dans un dictionnaire:
dict((i, a.count(i)) for i in a)
list.count(x)
renvoie le nombre de fois que x
apparaît dans une liste
voir: http://docs.python.org/tutorial/datastructures.html#more-on-lists
Étant donné un élément, comment puis-je compter ses occurrences dans une liste en Python?
Voici un exemple de liste:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
Il y a la méthode list.count
>>> l.count('b')
4
Cela fonctionne très bien pour n'importe quelle liste. Les tuples ont aussi cette méthode:
>>> t = Tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
Et puis il y a des collections.Counter. Vous pouvez vider n'importe quel itérable dans un compteur, pas seulement une liste, et le compteur conservera une structure de données du nombre d'éléments.
Usage:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Les compteurs sont basés sur les dictionnaires Python, leurs clés sont les éléments, donc les clés doivent être hashable. Ils sont fondamentalement comme des ensembles qui contiennent des éléments redondants.
collections.Counter
Vous pouvez ajouter ou soustraire avec iterables de votre compteur:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
Et vous pouvez également effectuer des opérations sur plusieurs ensembles avec le compteur:
>>> c2 = Counter(list('aabbxyz'))
>>> c - c2 # set difference
Counter({'a': 3, 'c': 3, 'b': 2, 'd': 2, 'e': 1})
>>> c + c2 # addition of all elements
Counter({'a': 7, 'b': 6, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c | c2 # set union
Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1, 'y': 1, 'x': 1, 'z': 1})
>>> c & c2 # set intersection
Counter({'a': 2, 'b': 2})
Une autre réponse suggère:
Pourquoi ne pas utiliser des pandas?
Les pandas sont une bibliothèque commune, mais ce n’est pas dans la bibliothèque standard. L'ajouter comme exigence n'est pas trivial.
Il existe des solutions intégrées pour ce cas d'utilisation dans l'objet liste lui-même ainsi que dans la bibliothèque standard.
Si votre projet ne nécessite pas déjà de pandas, il serait insensé d’en faire une nécessité uniquement pour cette fonctionnalité.
Si vous voulez compter toutes les valeurs à la fois vous pouvez le faire très rapidement en utilisant des tableaux numpy et bincount
comme suit
import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)
qui donne
>>> array([0, 3, 1, 1, 2])
J'ai comparé toutes les solutions proposées (et quelques nouvelles) avec perfplot (un de mes petits projets).
Pour des tableaux assez grands, il s'avère que
numpy.sum(numpy.array(a) == 1)
est légèrement plus rapide que les autres solutions.
numpy.bincount(a)
c'est ce que tu veux.
Code pour reproduire les parcelles:
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
2.
from collections import Counter
from collections import defaultdict
import numpy
import operator
import pandas
import perfplot
def counter(a):
return Counter(a)
def count(a):
return dict((i, a.count(i)) for i in set(a))
def bincount(a):
return numpy.bincount(a)
def pandas_value_counts(a):
return pandas.Series(a).value_counts()
def occur_dict(a):
d = {}
for i in a:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
def count_unsorted_list_items(items):
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
def operator_countof(a):
return dict((i, operator.countOf(a, i)) for i in set(a))
perfplot.show(
setup=lambda n: list(numpy.random.randint(0, 100, n)),
n_range=[2**k for k in range(20)],
kernels=[
counter, count, bincount, pandas_value_counts, occur_dict,
count_unsorted_list_items, operator_countof
],
equality_check=None,
logx=True,
logy=True,
)
Si vous pouvez utiliser pandas
, alors value_counts
est là pour le secours.
>>> import pandas as pd
>>> a = [1, 2, 3, 4, 1, 4, 1]
>>> pd.Series(a).value_counts()
1 3
4 2
3 1
2 1
dtype: int64
Il trie également automatiquement le résultat en fonction de la fréquence.
Si vous voulez que le résultat soit dans une liste, procédez comme suit
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Pourquoi ne pas utiliser de pandas?
import pandas as pd
l = ['a', 'b', 'c', 'd', 'a', 'd', 'a']
# converting the list to a Series and counting the values
my_count = pd.Series(l).value_counts()
my_count
Sortie:
a 3
d 2
b 1
c 1
dtype: int64
Si vous recherchez le décompte d’un élément particulier, dites a , essayez:
my_count['a']
Sortie:
3
# Python >= 2.6 (defaultdict) && < 2.7 (Counter, OrderedDict)
from collections import defaultdict
def count_unsorted_list_items(items):
"""
:param items: iterable of hashable items to count
:type items: iterable
:returns: dict of counts like Py2.7 Counter
:rtype: dict
"""
counts = defaultdict(int)
for item in items:
counts[item] += 1
return dict(counts)
# Python >= 2.2 (generators)
def count_sorted_list_items(items):
"""
:param items: sorted iterable of items to count
:type items: sorted iterable
:returns: generator of (item, count) tuples
:rtype: generator
"""
if not items:
return
Elif len(items) == 1:
yield (items[0], 1)
return
prev_item = items[0]
count = 1
for item in items[1:]:
if prev_item == item:
count += 1
else:
yield (prev_item, count)
count = 1
prev_item = item
yield (item, count)
return
import unittest
class TestListCounters(unittest.TestCase):
def test_count_unsorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = count_unsorted_list_items(inp)
print inp, exp_outp, counts
self.assertEqual(counts, dict( exp_outp ))
inp, exp_outp = UNSORTED_WIN = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(dict( exp_outp ), count_unsorted_list_items(inp) )
def test_count_sorted_list_items(self):
D = (
([], []),
([2], [(2,1)]),
([2,2], [(2,2)]),
([2,2,2,2,3,3,5,5], [(2,4), (3,2), (5,2)]),
)
for inp, exp_outp in D:
counts = list( count_sorted_list_items(inp) )
print inp, exp_outp, counts
self.assertEqual(counts, exp_outp)
inp, exp_outp = UNSORTED_FAIL = ([2,2,4,2], [(2,3), (4,1)])
self.assertEqual(exp_outp, list( count_sorted_list_items(inp) ))
# ... [(2,2), (4,1), (2,1)]
J'ai eu ce problème aujourd'hui et ai roulé ma propre solution avant que je pensais vérifier SO. Ce:
dict((i,a.count(i)) for i in a)
est vraiment très lent pour les grandes listes. Ma solution
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
est en fait un peu plus rapide que la solution Counter, du moins pour Python 2.7.
Pour compter le nombre d'éléments divers ayant un type commun:
li = ['A0','c5','A8','A2','A5','c2','A3','A9']
print sum(1 for el in li if el[0]=='A' and el[1] in '01234')
donne
3
, pas 6
itertools.groupby()
Une autre possibilité d’obtenir le décompte de tous les éléments de la liste pourrait être obtenue au moyen de itertools.groupby()
.
Avec "duplicate" count
from itertools import groupby
L = ['a', 'a', 'a', 't', 'q', 'a', 'd', 'a', 'd', 'c'] # Input list
counts = [(i, len(list(c))) for i,c in groupby(L)] # Create value-count pairs as list of tuples
print(counts)
Résultats
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Remarquez comment il combine les trois premiers a
en tant que premier groupe, tandis que les autres groupes de a
sont présents plus bas dans la liste. Cela est dû au fait que la liste de saisie L
n'a pas été triée. Cela peut être un avantage parfois si les groupes doivent en fait être séparés.
Avec des chiffres uniques
Si un nombre de groupes unique est souhaité, il suffit de trier la liste des entrées:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
Résultats
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
from collections import Counter
country=['Uruguay', 'Mexico', 'Uruguay', 'France', 'Mexico']
count_country = Counter(country)
output_list= []
for i in count_country:
output_list.append([i,count_country[i]])
print output_list
Liste de sortie:
[['Mexico', 2], ['France', 1], ['Uruguay', 2]]
Il a été suggéré d'utiliser numpy bincount , mais cela ne fonctionne que pour les tableaux 1d avec entiers non négatifs. En outre, le tableau résultant peut être déroutant (il contient les occurrences des entiers de min à max de la liste d'origine et définit à 0 les entiers manquants).
Une meilleure façon de procéder avec numpy consiste à utiliser la fonction unique avec l'attribut return_counts
défini sur True. Il retourne un tuple avec un tableau des valeurs uniques et un tableau des occurrences de chaque valeur unique.
# a = [1, 1, 0, 2, 1, 0, 3, 3]
a_uniq, counts = np.unique(a, return_counts=True) # array([0, 1, 2, 3]), array([2, 3, 1, 2]
et alors nous pouvons les jumeler comme
dict(Zip(a_uniq, counts)) # {0: 2, 1: 3, 2: 1, 3: 2}
Cela fonctionne également avec d'autres types de données et "listes 2d", par exemple.
>>> a = [['a', 'b', 'b', 'b'], ['a', 'c', 'c', 'a']]
>>> dict(Zip(*np.unique(a, return_counts=True)))
{'a': 3, 'b': 3, 'c': 2}
Peut-être pas le plus efficace, nécessite une passe supplémentaire pour éliminer les doublons.
Mise en œuvre fonctionnelle:
arr = np.array(['a','a','b','b','b','c'])
print(set(map(lambda x : (x , list(arr).count(x)) , arr)))
résultats :
{('c', 1), ('b', 3), ('a', 2)}
ou retourner comme dict
:
print(dict(map(lambda x : (x , list(arr).count(x)) , arr)))
résultats :
{'b': 3, 'c': 1, 'a': 2}
Le plus rapide utilise une boucle for et le stocke dans un Dict.
import time
from collections import Counter
def countElement(a):
g = {}
for i in a:
if i in g:
g[i] +=1
else:
g[i] =1
return g
z = [1,1,1,1,2,2,2,2,3,3,4,5,5,234,23,3,12,3,123,12,31,23,13,2,4,23,42,42,34,234,23,42,34,23,423,42,34,23,423,4,234,23,42,34,23,4,23,423,4,23,4]
#Solution 1 - Faster
st = time.monotonic()
for i in range(1000000):
b = countElement(z)
et = time.monotonic()
print(b)
print('Simple for loop and storing it in dict - Duration: {}'.format(et - st))
#Solution 2 - Fast
st = time.monotonic()
for i in range(1000000):
a = Counter(z)
et = time.monotonic()
print (a)
print('Using collections.Counter - Duration: {}'.format(et - st))
#Solution 3 - Slow
st = time.monotonic()
for i in range(1000000):
g = dict([(i, z.count(i)) for i in set(z)])
et = time.monotonic()
print(g)
print('Using list comprehension - Duration: {}'.format(et - st))
Résultat
#Solution 1 - Faster
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 234: 3, 23: 10, 12: 2, 123: 1, 31: 1, 13: 1, 42: 5, 34: 4, 423: 3}
Simple for loop and storing it in dict - Duration: 12.032000000000153
#Solution 2 - Fast
Counter({23: 10, 4: 6, 2: 5, 42: 5, 1: 4, 3: 4, 34: 4, 234: 3, 423: 3, 5: 2, 12: 2, 123: 1, 31: 1, 13: 1})
Using collections.Counter - Duration: 15.889999999999418
#Solution 3 - Slow
{1: 4, 2: 5, 3: 4, 4: 6, 5: 2, 34: 4, 423: 3, 234: 3, 42: 5, 12: 2, 13: 1, 23: 10, 123: 1, 31: 1}
Using list comprehension - Duration: 33.0
sum([1 for elem in <yourlist> if elem==<your_value>])
Cela retournera le nombre d'occurrences de votre_valeur
Bien que ce soit une question très ancienne, mais comme je n’ai pas trouvé de one-liner, j’en ai fait un.
# original numbers in list
l = [1, 2, 2, 3, 3, 3, 4]
# empty dictionary to hold pair of number and its count
d = {}
# loop through all elements and store count
[ d.update( {i:d.get(i, 0)+1} ) for i in l ]
print(d)
si vous voulez un nombre d'occurrences pour l'élément particulier:
>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> single_occurrences = Counter(z)
>>> print(single_occurrences.get("blue"))
3
>>> print(single_occurrences.values())
dict_values([3, 2, 1])
def countfrequncyinarray(arr1):
r=len(arr1)
return {i:arr1.count(i) for i in range(1,r+1)}
arr1=[4,4,4,4]
a=countfrequncyinarray(arr1)
print(a)