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 Countercounter.values()
returns a dict-values object, used for other methods such assum()
to get the total count of all elements.list(counter)
is used to list all unique elementsset(counter)
converts the counter into a Setcounter.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