Counters in Python?


A Counters is a container which keeps track to how many times equivalent values are added. Python counter class is a part of collections module and is a subclass of dictionary.

Python Counter

We may think of counter as an unordered collection of items where items are stored as dictionary keys and their count as dictionary value.

Counter items count can be positive, zero or negative integers. Though there is no restrict on its keys and values but generally values are intended to be numbers but we can store other object types too.

Initializing

Counter supports three forms of initialization. Its constructor can be called with a sequence of items, a dictionary containing keys and counts, or using keyword arguments mapping string names to counts.

import collections
print (collections.Counter(['a', 'b', 'c', 'a', 'b', 'b']))
print (collections.Counter({'a': 2, 'b': 3, 'c':1}))
print(collections.Counter(a=2, b=3, c=1))

The output from all three forms of initialization are the same -

Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})
Counter({'b': 3, 'a': 2, 'c': 1})

To create an empty counter, pass the counter with no argument and populate it via the update method.

import collections
c = collections.Counter()
print('Initial: ', c)
c.update('abcddcba')
print('Sequence: ', c)
c.update({'a': 1, 'd':5})
print('Dict: ', c)

Output

Initial: Counter()
Sequence: Counter({'a': 2, 'b': 2, 'c': 2, 'd': 2})
Dict: Counter({'d': 7, 'a': 3, 'b': 2, 'c': 2})

Accessing Counts

Once the counter is populated, it values can be fetched via dictionary API.

import collections
c = collections.Counter('abcddcba')
for letter in 'abcdef':
   print('%s : %d' %(letter, c[letter]))

Output

a : 2
b : 2
c : 2
d : 2
e : 0
f : 0

Counter does not raise KeyError for unknown items(like the items e & f we have mentioned in above program). If a value has not been seen in the input, its count is 0 (like for unknown item e & f in above output).

The elements() method returns an iterator that produces all of the items known to the Counter.

import collections
c = collections.Counter('Python Counters')
c['z'] = 0
print(c)
print(list(c.elements()))

Output

Counter({'t': 2, 'o': 2, 'n': 2, 'P': 1, 'y': 1, 'h': 1, ' ': 1, 'C': 1, 'u': 1, 'e': 1, 'r': 1, 's': 1, 'z': 0})
['P', 'y', 't', 't', 'h', 'o', 'o', 'n', 'n', ' ', 'C', 'u', 'e', 'r', 's']

The order of elements is not fixed, and items with counts less than zero are not included.

To produce common inputs out of n inputs and their respective counts we use most_common() function.

import collections
c = collections.Counter()
texts = '''Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa
qui officia deserunt mollit anim id est laborum.'''
for word in texts:
c.update(word.rstrip().lower())
print("Five most common letters in the texts: ")
for letter, count in c.most_common(5):
print("%s: %7d" %(letter, count))

Output

Five most common letters in the texts:
i: 42
e: 38
t: 32
o: 29
u: 29

Above example counts the letters appearing in the texts (or you can consider a file) to produce a frequency distribution, then prints the five most common. Leaving out the argument to most_common() produces a list of all the items, in order of frequency.

Arithmetic

Counter instances support arithmetic and set operations for aggregating results.

import collections
c1 = collections.Counter(['a', 'b', 'c', 'a' ,'b', 'b'])
c2 = collections.Counter('alphabet')
print('C1: ', c1)
print('C2: ', c2)
print ('\nCombined counts: ')
print(c1 + c2)
print('\nSubtraction: ')
print(c1 - c2)
print('\nIntersection (taking positive minimums): ')
print(c1 & c2)
print('\nUnion (taking maximums): ')
print(c1 | c2)

Output

C1: Counter({'b': 3, 'a': 2, 'c': 1})
C2: Counter({'a': 2, 'l': 1, 'p': 1, 'h': 1, 'b': 1, 'e': 1, 't': 1})
Combined counts:
Counter({'a': 4, 'b': 4, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})
Subtraction:
Counter({'b': 2, 'c': 1})
Intersection (taking positive minimums):
Counter({'a': 2, 'b': 1})
Union (taking maximums):
Counter({'b': 3, 'a': 2, 'c': 1, 'l': 1, 'p': 1, 'h': 1, 'e': 1, 't': 1})

Each time a new counter is produced through an operation, any items with zero or negative counts are discarded.

Updated on: 30-Jul-2019

3K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements