web-dev-qa-db-fra.com

Comment compter les occurrences d'un élément de liste?

Étant donné un élément, comment puis-je compter ses occurrences dans une liste en Python?

1231
weakish

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.

1571
Łukasz

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})
1474
user52028778

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]
215
user2314737

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)
60
tj80

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

44
Silfverstrom

É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.

Utilisation ultérieure de 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})

Pourquoi pas des pandas?

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é.

30
Aaron Hall

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])
29
flonk

J'ai comparé toutes les solutions proposées (et quelques nouvelles) avec perfplot (un de mes petits projets).

Comptage un article

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.

 enter image description here

Compter tous les articles

Comme établi auparavant ,

numpy.bincount(a)

c'est ce que tu veux.

 enter image description here


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,
    )
27
Nico Schlömer

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]]
16

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
14
Shoresh
# 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)]
11
Wes Turner

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.

11
D Blanc

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

6
eyquem

Compter tous les éléments avec 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)]
4
Tim Skov Jacobsen
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]]
4
Aakash Goel

Vous pouvez également utiliser countOf méthode d'un module intégré operator .

>>> import operator
>>> operator.countOf([1, 2, 3, 4, 1, 4, 1], 1)
3
3
vishes_shell

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}
3
AndyK

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}
2
blue-sky

Voici les trois solutions:

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
2
Akash Swain
sum([1 for elem in <yourlist> if elem==<your_value>])

Cela retournera le nombre d'occurrences de votre_valeur

1
whackamadoodle3000

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)
1
Harsh Gundecha

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])
0
DataBender
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)
0
ravi tanwar