How to Use Python Counters in 2023 (w/ 23 Code Examples)
We, as Python developers, may need to develop a piece of code that counts several repeated objects at once. There are different ways to perform this task. However, Python's Counter
class from the collections
module provides the most efficient and straightforward solution to count individual items in an iterable object.
In this tutorial, we will learn about the Counter
class and the basics of using it in Python.
After you finish this tutorial, you'll have a good understanding of
- What the
Counter
class is. - How to create a
Counter
object. - How to update an existing
Counter
object. - How to determine the most frequent item in an iterable object.
- How to combine or subtract
Counter
objects. - How to perform union and intersection on two
Counter
objects.
We assume you know the fundamentals of Python, including basic data structures and functions. If you're unfamiliar with these or eager to brush up your Python skill, you might like to try our Python Basics for Data Analysis – Dataquest.
What is the Python's Counter
Class
Python's Counter
is a subclass of the dictionary data type for counting hashable objects by creating a dictionary where the iterable's elements are stored as keys, and their counts are stored as values.
In other words, the Counter
's constructor function takes an iterable object, and returns a dictionary containing the frequency of each item in the iterable object as long as the objects are hashable.
The good news is that some of the arithmetic operations are applicable to Counter
objects.
In the following section, we will discuss using the Counter
to determine the frequency of hashable objects in lists, strings, and other iterable objects.
Working with the Counter Object
As mentioned earlier, the Counter
object provides an effortless way to count items in iterable objects quickly.
To demonstrate how the Counter
object works and show its result, let's start with importing the Counter
class from the collections
module and then apply it on a string, as follows:
from collections import Counter
a_str = 'barbara'
counter_obj = Counter(a_str)
print(counter_obj)
Counter({'a': 3, 'b': 2, 'r': 2})
As shown, the code above counts the letters in the word.
Let's make the output more appealing by adding the following lines to the previous code.
for item in counter_obj.items():
print("Item: ", item[0]," Frequency: ", item[1])
Item: b Frequency: 2
Item: a Frequency: 3
Item: r Frequency: 2
The Counter
class implements useful methods such as update()
and most_common([n])
. The update()
method takes an iterable object and adds it to the existing counter object.
Let's try it:
counter_obj.update("wallace")
print(counter_obj)
Counter({'a': 5, 'b': 2, 'r': 2, 'l': 2, 'w': 1, 'c': 1, 'e': 1})
The most_common([n])
method returns an ordered list of tuples with the n
most common
items and their counts.
print(counter_obj.most_common(1))
[('a', 5)]
The code above returns the most frequent item in the a_str
object.
To understand the usage of the Counter
object better, let's determine the most frequent item occurring in the following sentence:
"Fear leads to anger; anger leads to hatred; hatred leads to conflict; conflict leads to suffering."
Here's how we would do it:
quote_1 = "Fear leads to anger; anger leads to hatred; hatred leads to conflict; conflict leads to suffering."
words_1 = quote_1.replace(';','').replace('.','').split()
word_counts = Counter(words_1)
the_most_frequent = word_counts.most_common(1)
print(the_most_frequent)
[('leads', 4)]
In the code above, the Counter
object generates a dictionary that maps the hashable items in the input sequence to the number of occurrences, as follows:
{
'Fear': 1,
'leads': 4,
'to': 4,
'anger': 2,
'hatred': 2,
'conflict': 2,
'suffering': 1
}
As mentioned in the first section of this tutorial, one of the valuable features of Counter
objects is that they can be combined using mathematical operations. For example:
from pprint import pprint
quote_2 = "Fear, anger, and hatred essentially come from a lack of perspective as to what life is all about."
words_2 = quote_2.replace(',','').replace('.','').split()
dict_1 = Counter(words_1)
dict_2 = Counter(words_2)
pprint(dict_1)
print()
pprint(dict_2)
Counter({'leads': 4,
'to': 4,
'anger': 2,
'hatred': 2,
'conflict': 2,
'Fear': 1,
'suffering': 1})
Counter({'Fear': 1,
'anger': 1,
'and': 1,
'hatred': 1,
'essentially': 1,
'come': 1,
'from': 1,
'a': 1,
'lack': 1,
'of': 1,
'perspective': 1,
'as': 1,
'to': 1,
'what': 1,
'life': 1,
'is': 1,
'all': 1,
'about': 1})
Now, we're able to combine or subtract these two Counter instances. Let's try them:
pprint(dict_1 + dict_2)
Counter({'to': 5,
'leads': 4,
'anger': 3,
'hatred': 3,
'Fear': 2,
'conflict': 2,
'suffering': 1,
'and': 1,
'essentially': 1,
'come': 1,
'from': 1,
'a': 1,
'lack': 1,
'of': 1,
'perspective': 1,
'as': 1,
'what': 1,
'life': 1,
'is': 1,
'all': 1,
'about': 1})
pprint(dict_1 - dict_2)
Counter({'leads': 4,
'to': 3,
'conflict': 2,
'anger': 1,
'hatred': 1,
'suffering': 1})
So far, we have tried the Counter
object with string values. In the same way, we're able to give list, tuple, or dictionary objects to Counter
and count the frequency of their items. Let's explore them in the following sections.
Python'sCounter
with List, Tuple, and Dictionary Objects
To explore how list, tuple, and dictionary objects given to Python's Counter
will be converted to hashable objects in the form of key-value pairs, let's consider a boutique that sells T-shirts in three colors, green, white, and red.
The following iterable objects show the T-shirt sales on two consecutive days, as follows:
sales_day_1 = ['red','green','white','red','red','green', 'white','green','red','red','red', 'white', 'white']
sales_day_2 = ('red','red','green','white','green','white','red','red','green', 'white','green','red','green','red','red')
price = {'red':74.99, 'green':83.99, 'white':51.99}
sales_day_1_counter = Counter(sales_day_1)
sales_day_2_counter = Counter(sales_day_2)
price_counter = Counter(price)
total_sales = sales_day_1_counter + sales_day_2_counter
sales_increment = sales_day_2_counter - sales_day_1_counter
minimum_sales = sales_day_1_counter & sales_day_2_counter
maximum_sales = sales_day_1_counter | sales_day_2_counter
print("Total Sales:", total_sales)
print("Sales Increment over Two Days:", sales_increment)
print("Minimun Sales:", minimum_sales)
print("Maximum Sales:", maximum_sales)
Total Sales: Counter({'red': 13, 'green': 8, 'white': 7})
Sales Increment over Two Days: Counter({'green': 2, 'red': 1})
Minimun Sales: Counter({'red': 6, 'green': 3, 'white': 3})
Maximum Sales: Counter({'red': 7, 'green': 5, 'white': 4})
In the example above, the sales_increment
Counter doesn't contain white shirts since the Counter object doesn't show negative values. That's why the Counter contains only green and red shirts. The number of white shirts is decreased to -1 and ignored.
We have used the &
and |
operators in the code above to return minimum and maximum sales of each T-shirt's color. Let's discuss these two operators here. The intersection operator (&
) returns the objects with minimum counts from both counters, while the union operator (|
) returns the maximum counts from both counters.
To calculate the total sales of each color, we can use the following snippet:
for color,quantity in total_sales.items():
print(f"Total sales of '{color}' T-shirts: ${quantity*price_counter[color]:.2f}")
Total sales of 'red' T-shirts: $974.87
Total sales of 'green' T-shirts: $671.92
Total sales of 'white' T-shirts: $363.93
To retrieve the original data used to create a Counter
, we can use the elements()
method, as follows:
for item in sales_day_1_counter.elements():
print(item)
red
red
red
red
red
red
green
green
green
white
white
white
white
The output above reveals that the Counter's elements have been returned in the same order as in the sales_day_1_counter
object.
Conclusions
This tutorial discussed Python's Counter
, which provides an efficient approach to counting the number of items in an iterable object without dealing with loops and different data structures. We also learned about the Counter
's methods and operators that help us to take the most insights out of the data stored into collections.
I hope that you have learned something new today. Feel free to connect with me on LinkedIn or Twitter.