Counter in Python

A Counter is a subclass of dict and is part of the Collections module. It is used for counting hashable objects.

It is an unordered collection where the elements are stored as Dictionary Keys and their counts are the values.

Counter Object format: {element1: count1, element2: count2}

Elements are counted from an iterable or initialized from another mapping (or counter)

Initialization of the Counter object is done using the Counter() call.

We can also pass an iterable into the call and get the corresponding mapped object.

>>> from collections import Counter
>>> # Empty Counter object
>>> c = Counter()
>>> c
Counter()

>>> # Tuple of values
>>> d = Counter(a=1, b=2, c=1)
>>> d
Counter({'b': 2, 'a': 1, 'c': 1})

>>> # Pass a list, which is an iterable
>>> e = Counter(['a', 'b', 'a', 'c'])
>>> e
Counter({'a': 2, 'b': 1, 'c': 1})

>>> # Pass a string, also an iterable
>>> f = Counter('red-dish')
>>> f
Counter({'d': 2, 'r': 1, 'e': 1, '-': 1, 'i': 1, 's': 1, 'h': 1})

>>> # Pass a Dictionary
>>> g = Counter({'a': 10, 'b': 11})
>>> g
Counter({'b': 11, 'a': 10})

Note that when the Counter object is displayed, the key-value pairs are displayed on the order of descending counts.

Counter objects have a dictionary interface except that they return a zero count for missing items instead of raising a KeyError.


Counter Methods

1. Get the count of individual elements

Individual element counts are accessed in the same way as that of a Dictionary, meaning that counter_object[key] gives the count of key.

>>> c = Counter(a=1, b=2, c=1)
>>> c
Counter({'b': 2, 'a': 1, 'c': 1})
>>> c['b']
2
>>> c['d'] # Does not give KeyError, unlike a Dictionary
0

2. Set the count of elements

To set the count of an element, use counter_object[key] = value. If key does not exist, it gets added to the Counter Dictionary, along with the new count.

>>> c = Counter(a=1, b=2, c=1)
>>> c
Counter({'b': 2, 'a': 1, 'c': 1})
>>> c['d'] = 4
>>> c
Counter({'d': 4, 'b': 2, 'a': 1, 'c': 1})

3. Remove elements from the Counter

To remove a key from the Counter object, use del counter_object[key].

>>> del c['d']
>>> c
Counter({'b': 2, 'a': 1, 'c': 1})

4. elements()

This method returns an iterator over the elements, values of which are repeated as many times as their counts. This method ignores all elements that have their counts less than one.

>>> c
Counter({'b': 2, 'a': 1, 'c': 1})
>>> c['d'] = -1
>>> c
>>> c.elements()
<itertools.chain object at 0x102e2a208>
>>> type(c.elements())
<class 'itertools.chain'>
>>> for i in c.elements():
...     print(i)
...
a
b
b
c
>>> list(c.elements())
['a', 'b', 'b', 'c']

>>> c['d'] = -1
>>> c
Counter({'b': 2, 'a': 1, 'c': 1, 'd': -1})
>>> # Ignores d since count[d] < 1
>>> list(c.elements())
['a', 'b', 'b', 'c']

5. most_common(n)

This returns a list of the n most common elements and their counts from the most common to the least. If n is omitted or None, most_common() returns all elements in the counter. Elements with equal counts are ordered arbitrarily.

>>> c
Counter({'b': 2, 'a': 1, 'c': 1, 'd': -1})
>>> c.most_common()
[('b', 2), ('a', 1), ('c', 1), ('d', -1)]
>>> c.most_common(2)
[('b', 2), ('a', 1)]

6. subtract(iterable/mapping)

This returns a mapping/iterable after subtracting the contents of the two iterables/mappings. Elements are not replaced, and only their counts are subtracted.

>>> a = Counter('redblue')
>>> a
Counter({'e': 2, 'r': 1, 'd': 1, 'b': 1, 'l': 1, 'u': 1})
>>> b = Counter('blueorange')
>>> b
Counter({'e': 2, 'b': 1, 'l': 1, 'u': 1, 'o': 1, 'r': 1, 'a': 1, 'n': 1, 'g': 1})

>>> # Subtracts b from a and updates a accordingly
>>> a.subtract(b)
>>> a
Counter({'d': 1, 'r': 0, 'e': 0, 'b': 0, 'l': 0, 'u': 0, 'o': -1, 'a': -1, 'n': -1, 'g': -1})

7. update(iterable/mapping)

This is similar to subtract(), but only adds counts instead of subtracting them.

>>> a = Counter('12321')
>>> b = Counter('23432')
>>> a
Counter({'1': 2, '2': 2, '3': 1})
>>> b
Counter({'2': 2, '3': 2, '4': 1})

>>> # Add counts into a
>>> a.update(b)
>>> a
Counter({'2': 4, '3': 3, '1': 2, '4': 1})

Other Counter() methods

  • counter.clear() is used to reset the counts of all elements in the Counter
  • counter.values() returns a dict-values object, used for other methods such as sum() to get the total count of all elements.
  • list(counter) is used to list all unique elements
  • set(counter) converts the counter into a Set
  • counter.items() returns a list of (key, value) pairs in the Counter.
  • counter += Counter() removes all elements with zero or negative counts

Arithmetic Operations on Counters

We can use basic arithmetic operations on Counters, like addition, subtraction, union, and intersection.

>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d
Counter({'a': 4, 'b': 3})

>>> # Subtract c, d while keeping only positive counts
>>> c - d
Counter({'a': 2})

>>> # Intersection of c, d (Min(c, d))
>>> c & d
Counter({'a': 1, 'b': 1})

>>> # Union of c, d (Max (c, d))
>>> c | d
Counter({'a': 3, 'b': 2})

Conclusion

We learned about the Counter class, which gives us objects having a mapping to each element to its count. We also learned about some of the methods that collections.Counter provides us with, for manipulating the Counter objects.

References

Python Collections Documentation: https://docs.python.org/2/library/collections.html

JournalDev Article on Python’s Counter: https://www.journaldev.com/20806/python-counter-python-collections-counter