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.
How to count the occurrences of a list item in Python?
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})
Answer #2:
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]
Given an item, how can I count its occurrences in a list in Python?
Here’s an example list:
>>> l = list('aaaaabbbbcccdde')
>>> l
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']
list.count
There’s the list.count
method
>>> l.count('b')
4
This works fine for any list. Tuples have this method as well:
>>> t = tuple('aabbbffffff')
>>> t
('a', 'a', 'b', 'b', 'b', 'f', 'f', 'f', 'f', 'f', 'f')
>>> t.count('f')
6
collections.Counter
And then there’s collections.Counter. You can dump any iterable into a Counter, not just a list, and the Counter will retain a data structure of the counts of the elements.
Usage:
>>> from collections import Counter
>>> c = Counter(l)
>>> c['b']
4
Counters are based on Python dictionaries, their keys are the elements, so the keys need to be hashable. They are basically like sets that allow redundant elements into them.
Further usage of collections.Counter
You can add or subtract with iterables from your counter:
>>> c.update(list('bbb'))
>>> c['b']
7
>>> c.subtract(list('bbb'))
>>> c['b']
4
And you can do multi-set operations with the counter as well:
>>> 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})
Why not pandas?
Another answer suggests:
Why not use pandas?
Pandas is a common library, but it’s not in the standard library. Adding it as a requirement is non-trivial.
There are built-in solutions for this use-case in the list object itself as well as in the standard library.
If your project does not already require pandas, it would be foolish to make it a requirement just for this functionality.
Answer #4:
If you want to count all values at once you can do it very fast using numpy arrays and bincount
as follows
import numpy as np
a = np.array([1, 2, 3, 4, 1, 4, 1])
np.bincount(a)
which gives
>>> array([0, 3, 1, 1, 2])
Answer #5:
If you can use pandas
, then value_counts
is there for rescue.
>>> 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
It automatically sorts the result based on frequency as well.
If you want the result to be in a list of list, do as below
>>> pd.Series(a).value_counts().reset_index().values.tolist()
[[1, 3], [4, 2], [3, 1], [2, 1]]
Answer #6:
Why not using Pandas?
import pandas as pd
my_list = ['a', 'b', 'c', 'd', 'a', 'd', 'a']
# converting the list to a Series and counting the values
my_count = pd.Series(my_list).value_counts()
my_count
Output:
a 3
d 2
b 1
c 1
dtype: int64
If you are looking for a count of a particular element, say a, try:
my_count['a']
Output:
3
How to count the occurrences of a list item in Python?
I had this problem today and rolled my own solution before I thought to check SO. This:
dict((i,a.count(i)) for i in a)
is really, really slow for large lists. My solution
def occurDict(items):
d = {}
for i in items:
if i in d:
d[i] = d[i]+1
else:
d[i] = 1
return d
is actually a bit faster than the Counter solution, at least for Python 2.7.
Answer #8:
Count of all elements with itertools.groupby()
Another possibility for getting the count of all elements in the list could be by means of itertools.groupby()
.
With “duplicate” counts
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)
Returns
[('a', 3), ('t', 1), ('q', 1), ('a', 1), ('d', 1), ('a', 1), ('d', 1), ('c', 1)]
Notice how it combined the first three a
‘s as the first group, while other groups of a
are present further down the list. This happens because the input list L
was not sorted. This can be a benefit sometimes if the groups should in fact be separate.
With unique counts
If unique group counts are desired, just sort the input list:
counts = [(i, len(list(c))) for i,c in groupby(sorted(L))]
print(counts)
Returns
[('a', 5), ('c', 1), ('d', 2), ('q', 1), ('t', 1)]
Note: For creating unique counts, many of the other answers provide easier and more readable code compared to the groupby
solution. But it is shown here to draw a parallel to the duplicate count example.
Answer #9:
Below are the three solutions:
Fastest is using a for loop and storing it in a 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))
Result
#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
Hope you learned something from this post.
Follow Programming Articles for more!