Matplotlib Histograms

plt.hist() groups numeric data into bins and draws a bar for each bin's count, revealing the shape of a distribution rather than comparing named categories.

Histograms vs. Bar Charts

A histogram looks like a bar chart, but it answers a different question. A bar chart compares a value across separate named categories, such as sales by region. A histogram instead takes one long list of numbers, such as everyone's height in a class, and shows how many values fall into each range, called a bin. There are no separate categories in the input data — Matplotlib creates the groups for you.

Basic Histogram

Pass a single array of numbers to plt.hist(). By default Matplotlib splits the data's range into 10 equal-width bins and draws a bar for the count of values in each one.

Example

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(1)
delivery_times = np.random.normal(loc=30, scale=5, size=200)

plt.hist(delivery_times)
plt.xlabel("Delivery time (minutes)")
plt.ylabel("Number of deliveries")
plt.title("Distribution of delivery times")
plt.show()

Choosing the Number of Bins

The bins argument controls how many equal-width groups the data is split into. Too few bins can hide real structure in the data, such as two overlapping peaks; too many bins can make the chart look noisy and jagged, dominated by random gaps. There is no single right number — it is common to try a few values and see which one best shows the shape of the data.

Example

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(0)
ages = np.random.randint(18, 70, size=150)

plt.hist(ages, bins=8, color="mediumpurple", edgecolor="white")
plt.xlabel("Age")
plt.ylabel("Number of customers")
plt.title("Customer age distribution (8 bins)")
plt.show()
Note: bins can also be a list of the bin edges themselves, such as bins=[0, 18, 35, 50, 65, 100], when you want uneven, meaningful ranges — like age brackets — instead of equal-width bins.

Passing two arrays to plt.hist() in separate calls, with alpha set below 1 so both are visible, lets you compare how two groups are distributed on the same axes.

Example

import matplotlib.pyplot as plt
import numpy as np

np.random.seed(2)
before_training = np.random.normal(loc=20, scale=4, size=100)
after_training = np.random.normal(loc=25, scale=3, size=100)

plt.hist(before_training, bins=10, alpha=0.6, label="Before training")
plt.hist(after_training, bins=10, alpha=0.6, label="After training")
plt.xlabel("5K run time (minutes)")
plt.ylabel("Number of runners")
plt.legend()
plt.show()
ArgumentEffect
binsNumber of equal-width groups, or a list of explicit bin edges
rangeThe (min, max) span the bins should cover, instead of the data's own min and max
densityWhen True, scales bar heights so the total area sums to 1, useful for comparing differently sized datasets
cumulativeWhen True, each bar shows the running total up to that bin instead of just that bin's count

Exercise: Matplotlib Histograms

What kind of data does plt.hist() typically visualize?