Categories
count list python

How do I count the occurrences of a list item?

2011

Given a single item, how do I count occurrences of it in a list, in Python?


A related but different problem is counting occurrences of each different element in a collection, getting a dictionary or list as a histogram result instead of a single integer. For that problem, see Using a dictionary to count the items in a list.

2

  • 2

    For reference, this thread on meta discussed the reason why both these threads remained open as-is.

    Jul 29 at 0:25

  • 2

    As discussed on meta, this question is nominally about counting a single item. Over the years, it’s attracted multiple (good) answers about the related but significantly different problem of histogramming; counting every different element, which should use an O(n) algorithm, not .count for every element which is O(n^2). Ideally those should be in (a) different Q&A(s), but for now they’re here.

    Jul 30 at 2:20

2377

If you only want a single item’s count, use the count method:

>>> [1, 2, 3, 4, 1, 4, 1].count(1)
3

Important: this is very slow if you are counting multiple different items

Each count call goes over the entire list of n elements. Calling count in a loop n times means n * n total checks, which can be catastrophic for performance.

If you want to count multiple items, use Counter, which only does n total checks.

2

  • 18

    mylist = [1,7,7,7,3,9,9,9,7,9,10,0] print sorted(set([i for i in mylist if mylist.count(i)>2]))

    – cpp-coder

    Sep 9, 2017 at 19:15


  • 5

    Counting unique elements in my case yielded the following timings: 114.19seconds with list.count(), 0.53 seconds with numpy.unique(list, return_counts = True) and 0.17 seconds with Counter. The difference is striking.

    Feb 10 at 19:14


2275

Use Counter if you are using Python 2.7 or 3.x and you want the number of occurrences for each element:

>>> from collections import Counter
>>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> Counter(z)
Counter({'blue': 3, 'red': 2, 'yellow': 1})

7

  • 3

    I have found that when using this a lot (talking about millions of strings) that it is very slow because of its calls to isinstance. So if you are certain about the data that you’re working with, it might be better to write a custom function without type and instance checking.

    Jun 19, 2018 at 21:26


  • 7

    @BramVanroy: What isinstance calls? Even with millions of strings, calling Counter only involves one isinstance call, to check whether its argument is a mapping. You most likely misjudged what’s eating all your time.

    Nov 14, 2018 at 4:08

  • 1

    You misinterpreted what I meant: Counter checks the types of your data before it creates the Counter. This takes relatively much time and if you know the type of your data in advance. If you look at Counter’s update method, you’ll see it has to go through three if-statements before doing something. If you call update frequently, this adds up quickly. When you have control over your data and you know that the input will be indeed an iterable, then you can skip the first two checks. As I said, I only noticed this when working with millions of updates so it’s an edge case.

    Nov 14, 2018 at 8:45

  • 8

    @BramVanroy: If you’re performing millions of updates rather than just counting millions of strings, that’s a different story. The optimization effort in Counter has gone into counting large iterables, rather than counting many iterables. Counting a million-string iterable will go faster with Counter than with a manual implementation. If you want to call update with many iterables, you may be able to speed things up by joining them into one iterable with itertools.chain.

    Nov 14, 2018 at 18:20

  • 12

    In case you want to sort the results how-to-sort-counter-by-value-python –> x = Counter({'a':5, 'b':3, 'c':7}) x.most_common()

    – Javi

    Dec 22, 2020 at 9:27


344

Counting the occurrences of one item in a list

For counting the occurrences of just one list item you can use count()

>>> l = ["a","b","b"]
>>> l.count("a")
1
>>> l.count("b")
2

Counting the occurrences of all items in a list is also known as “tallying” a list, or creating a tally counter.

Counting all items with count()

To count the occurrences of items in l one can simply use a list comprehension and the count() method

[[x,l.count(x)] for x in set(l)]

(or similarly with a dictionary dict((x,l.count(x)) for x in set(l)))

Example:

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

Counting all items with Counter()

Alternatively, there’s the faster Counter class from the collections library

Counter(l)

Example:

>>> l = ["a","b","b"]
>>> from collections import Counter
>>> Counter(l)
Counter({'b': 2, 'a': 1})

How much faster is Counter?

I checked how much faster Counter is for tallying lists. I tried both methods out with a few values of n and it appears that Counter is faster by a constant factor of approximately 2.

Here is the script I used:

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)

And the output:

Counter():  [0.46062711701961234, 0.4022796869976446, 0.3974247490405105]
count():    [7.779430688009597, 7.962715800967999, 8.420845870045014]

3

  • 49

    Counter is way faster for bigger lists. The list comprehension method is O(n^2), Counter should be O(n).

    – fhucho

    Nov 11, 2015 at 22:34


  • 44

    Counter is not faster by a factor of 2, Counter is faster by a factor of n (O(n^2) vs O(n)).

    – Martijn Pieters

    May 23, 2017 at 10:13

  • 2

    I have found that when using this a lot (talking about millions of strings) that it is very slow because of its calls to isinstance. So if you are certain about the data that you’re working with, it might be better to write a custom function without type and instance checking.

    Jun 19, 2018 at 21:27