Skip to content

Matplotlib - Histogram

A histogram is a powerful graphical representation of the distribution of numerical data. It groups data points into specified ranges (bins) and plots bars whose heights represent the frequency (count) of data points falling into each bin.

Histograms help visualize:

  • The central tendency (e.g., where data clusters).
  • The spread or variability of the data.
  • The shape of the distribution (e.g., symmetric, skewed).
  • The presence of gaps or outliers.

The ax.hist() method (object-oriented API) computes and draws the histogram.

ParameterDescription
xInput data (1D array-like or sequence of arrays for multiple histograms).
binsDefines the bins. Can be: An integer (number of equal-width bins), a sequence (defining bin edges), or a string (e.g., ‘auto’, ‘fd’, ‘sqrt’ for automatic binning strategies).
rangeA tuple (min, max) specifying the lower and upper range of the bins. Values outside this range are ignored.
densityIf True, the result is the value of the probability density function at the bin, normalized such that the area (not height) of the histogram integrates to 1. Useful for comparing distributions with different sample sizes.
cumulativeIf True, computes a cumulative histogram where each bin shows the count in that bin plus all bins for smaller values.
histtypeType of histogram: ‘bar’ (default, traditional bars), ‘barstacked’ (stacks multiple datasets), ‘step’ (generates an unfilled line plot), ‘stepfilled’ (generates a filled line plot).
colorColor of the bars/steps.
edgecolorColor of the bar edges.
alphaTransparency level (0=transparent, 1=opaque).
labelLabel for the dataset, used when creating legends.

Let’s plot a histogram of simulated exam scores to visualize their distribution.

import matplotlib.pyplot as plt
import numpy as np
# Simulate some exam score data (e.g., normally distributed around 75)
rng = np.random.default_rng(seed=123)
scores = rng.normal(loc=75, scale=15, size=200)
# Ensure scores are within a plausible range (e.g., 0-100)
scores = np.clip(scores, 0, 100)
# Create Figure and Axes
fig, ax = plt.subplots(figsize=(8, 5))
# Define the bins explicitly
bins = [0, 50, 60, 70, 80, 90, 100]
# Alternative: Let Matplotlib decide bins: bins=10 or bins='auto'
# Plot the histogram
counts, bin_edges, patches = ax.hist(
scores,
bins=bins,
color='skyblue',
edgecolor='black',
alpha=0.8,
label='Student Scores'
)
# Customize the plot
ax.set_title('Distribution of Exam Scores')
ax.set_xlabel('Score Range')
ax.set_ylabel('Number of Students (Frequency)')
# Set x-ticks to match bin edges for clarity
ax.set_xticks(bin_edges)
ax.tick_params(axis='x', rotation=45)
# Add text labels showing the count above each bar (optional)
for count, patch in zip(counts, patches):
height = patch.get_height()
if height > 0: # Only label non-empty bars
ax.annotate(f'{int(count)}',
xy=(patch.get_x() + patch.get_width() / 2, height),
xytext=(0, 5), # 5 points vertical offset
textcoords='offset points',
ha='center', va='bottom')
ax.legend()
ax.grid(axis='y', linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
# Output the calculated counts and bin edges (returned by ax.hist)
print("Counts per bin:", counts)
print("Bin edges:", bin_edges)

This code generates a histogram showing the number of students whose scores fall into predefined bins (0-50, 50-60, etc.). The bars are styled, labels and a title are added, and the x-ticks are explicitly set to the bin edges. Optional annotations display the exact count above each bar. The ax.hist function conveniently returns the calculated counts, bin edges, and the bar patch objects.

Setting density=True changes the y-axis to represent probability density instead of raw frequency. The area of each bar then corresponds to the probability of a data point falling within that bin. This is useful for comparing datasets of different sizes or overlaying a theoretical probability density function (PDF).