Creating a Frequency Bar Chart from a DataFrame


Bar charts are excellent visualizations to show the frequency of categorical data. Often, it is valuable to quickly create a frequency bar chart from a DataFrame of thousands of observations.

When visualizing complex data, such as a simulation of guessing on a true/false exam with 10 questions, we can quickly create a frequency bar chart of this data:

import pandas as pd
import random

# Simulation of Randomly Guessing on a 10-Question True/False Exam:
data = []
for i in range(10000):
  # Simulate taking a 10-question true/false exam, guessing on every question:
  correctAnswers = 0
  for q in range(10):
    correctAnswers = random.choice([0, 1])

  d = {"correctAnswers": correctAnswers}
  data.append(d)

df = pd.DataFrame(data)

# Creating a Frequency Bar Chart of Correct Answers:
freq = df["correctAnswers"].value_counts().sort_index()
freq.plot.bar(title="# Correct Answers when Guessing on a 10-Question True/False Exam")
Creating a frequency bar chart visualizing the simulation results of 10,000 students randomly guessing on a 10-question true/false exam

Creating a Frequency Bar Chart

To understand the code to create a frequency bar chart, let's start with a simple DataFrame that stores data about each pizza that was ordered today:

import pandas as pd

df = pd.DataFrame([
  {"pizzaOrder": "Cheese", "cost": 14.99},
  {"pizzaOrder": "Cheese", "cost": 14.99},
  {"pizzaOrder": "Pepperoni", "cost": 16.99},
  {"pizzaOrder": "Cheese", "cost": 14.99},
  {"pizzaOrder": "Veggie", "cost": 16.99},
  {"pizzaOrder": "Veggie", "cost": 16.99},
  {"pizzaOrder": "Pepperoni", "cost": 16.99},
  {"pizzaOrder": "Veggie", "cost": 16.99},
  {"pizzaOrder": "Cheese", "cost": 14.99},
  {"pizzaOrder": "Cheese", "cost": 14.99},
])

df
pizzaOrdercost
0Cheese14.99
1Cheese14.99
2Pepperoni16.99
3Cheese14.99
4Veggie16.99
5Veggie16.99
6Pepperoni16.99
7Veggie16.99
8Cheese14.99
9Cheese14.99
Creating a DataFrame of the 10 pizzas sold today

Using this DataFrame, the bar chart graphs the price of each pizza in the list and isn't extremely useful:

# A not-so-useful bar chart:
df.plot.bar()
A not-so-useful bar chart

Finding the Counts of Unique Values

The panda's function value_counts() counts the number of times each unique value appears in a column of a DataFrame. In our sample DataFrame, we can count the unique values of the pizzaOrder:

df["pizzaOrder"].value_counts()
Cheese       5
Veggie       3
Pepperoni    2
Name: pizzaOrder, dtype: int64
Using value_counts() on the pizzaOrder column of the DataFrame

Similarly, we can find the unique values for the cost (value_counts() works with numeric data in addition to strings!):

df["cost"].value_counts()
14.99    5
16.99    5
Name: cost, dtype: int64
Using value_counts() on the cost column of the DataFrame

Creating a Bar Chart of Data Frequency (Counts)

When we use the value_counts() functions, the result is a Series and can be directly visualized -- it's common to see all of this done in a single line!

A frequency bar chart of the different types of pizza:

df["pizzaOrder"].value_counts().plot.bar(title="Pizzas Ordered Today")
Visualizing the frequency of different types of pizza orders today with a bar chart

Similarly, a frequency bar chart of the different prices of pizza today:

df["cost"].value_counts().plot.bar(title="Price of Pizzas Ordered Today")
Visualizing the cost of different pizza orders today with a bar chart

Sorting the Bar Chart

When working with numeric values, sorting the order in which the values appear in the bar chart becomes critical. There are two ways we might need to sort the data:

  • Sorting the data based on the category (ex: by the pizza toppings) so that the values along the x-axis are ordered, OR
  • Sorting the data based on the frequency (the number of occurrences) so the categories are in increasing/decreasing frequency

We'll explore an simulation to see the two ways to sor the data.

Application: Large Scale Simulation of Guessing on an Exam

An extremely common application of frequency bar charts is in the exploration of simulation results. For example, the following code simulates taking an exam with 10 true/false questions and guessing on each question. The DataFrame stores the result of how many questions each of the 10,000 simulated students answers correctly when guessing randomly:

import pandas as pd
import random

data = []
for i in range(10000):
  # Simulate taking a 10-question true/false exam, guessing on every question:
  correctAnswers = 0
  for q in range(10):
    correctAnswers = random.choice([0, 1])

  d = {"correctAnswers": correctAnswers}
  data.append(d)

df = pd.DataFrame(data)
df
correctAnswers
02
12
28
36
46
......
99957
99964
99974
99985
99995
Simulating 10,000 randomly guessing on a 10 question true/false exam

By using value_counts() and plot.bar(), we can quickly visualize the distribution of the simulation:

df["correctAnswers"].value_counts().plot.bar(title="# Correct Answers when Guessing on a 10-Question True/False Exam")
Creating a simple frequency bar chart of the number of correct answers from the simulation

Sorting By Frequency

By default, value_counts() sorts the list of values by frequency so that the most common value appears first on the list returned by value_counts() and will display on the left-hand side of the chart.

df["correctAnswers"].value_counts()
5     2404
4     2074
6     2032
7     1214
3     1201
8      427
2      423
1      109
9       97
0       13
10       6
Name: correctAnswers, dtype: int64
Viewing the default, frequency-sorted output of the value_counts() function

This creates a visualization with decreasing frequency moving from left-to-right, but with out-of-order data listed along the x-axis (note that the x-axis is 5, 4, 6, 7, 3 ...):

Frequency bar chart visualizing the simulation results of 10,000 students randomly guessing on a 10-question true/false exam, sorted by frequency

Sorting by Category/Index

It is common to want to sort by the category (stored in the index of the Series returned by value_counts()). To create a bar chart sorted by the index, we add sort_index() after value_counts(). The result is that the data is now sorted by the category name instead of the frequency:

freq = df["correctAnswers"].value_counts().sort_index()
freq
0       13
1      109
2      423
3     1201
4     2074
5     2404
6     2032
7     1214
8      427
9       97
10       6
Name: correctAnswers, dtype: int64
Sorting the value_counts() output by the category label (index)

Creating the bar chart:

freq = df["correctAnswers"].value_counts().sort_index()
freq.plot.bar(title="# Correct Answers when Guessing on a 10-Question True/False Exam")
Creating a category-sorted frequency bar chart

We find our visualization now organizes the data by the category instead of the frequency:

Frequency bar chart visualizing the simulation results of 10,000 students randomly guessing on a 10-question true/false exam, sorted by category