Heatmap Plot Gallery¶
Heatmap plots visualise 2D data as a colour-coded matrix with cell values annotated in place. They're the right pick when the eye needs to compare cell-to-cell magnitude across two categorical dimensions while still being able to read exact numbers.
Heatmap plots excel at:
- Performance grids: compare a metric across regions x quarters or stores x weeks
- Migration matrices: show movement between segments over a period
- Conversion or footfall patterns: spot weekday vs weekend or daypart effects
- Confusion matrices: read classification results at a glance
import matplotlib.pyplot as plt
import pandas as pd
from openretailscience.plots import heatmap
Basic Heatmap¶
The simplest call: pass a wide-format DataFrame and the index becomes the y-axis, the columns the x-axis. Cell values are annotated in place, and the colour intensity tracks the underlying number. Pick this shape when the data is already a small matrix you want to compare cell by cell.
heatmap.plot(
regional_quarterly,
cbar_label="Revenue ($000s)",
eyebrow="Regional performance",
title="East leads every quarter; North gains the most ground Q1 to Q4",
subtitle="Quarterly revenue ($000s) by region, full year",
)
plt.show()
Percentage Formatting¶
Pass cbar_format to control how cell values are rendered. The format string follows matplotlib's StrMethodFormatter syntax (e.g. "{x:.1%}" for percentages with one decimal, "{x:,.0f}" for thousands separators).
Note: in the default colormap_style="discrete" the colorbar is anchored with fixed "Low"/"High" labels and the format only applies to in-cell text. Switch to colormap_style="continuous" (shown here) when you want the format applied to the colorbar tick labels too.
heatmap.plot(
channel_conversion,
cbar_label="Conversion rate",
cbar_format="{x:.1%}",
colormap_style="continuous",
eyebrow="Marketing channels",
title="Google Ads converts highest every week; Social Media stays the laggard",
subtitle="Weekly conversion rate by marketing channel",
)
plt.show()
Continuous Colormap¶
Use colormap_style="continuous" for a smooth gradient when fine-grained magnitude differences matter more than reading exact values per cell. The default "discrete" style buckets values into 5 stepped bins for cleaner reading alongside cell annotations.
heatmap.plot(
regional_quarterly,
cbar_label="Revenue ($000s)",
colormap_style="continuous",
eyebrow="Regional performance",
title="Continuous gradient highlights gradual differences across cells",
subtitle="Same regional data, smooth colormap rather than stepped bins",
)
plt.show()
X-Axis Labels on Top¶
Set x_labels_position="top" to move the column labels above the matrix. Reads more naturally when the columns represent a time progression (months, weeks, periods since acquisition) and the eye should track left-to-right alongside the row labels.
heatmap.plot(
category_monthly_index,
cbar_label="Footfall index",
x_labels_position="top",
eyebrow="Seasonality",
title="Electronics footfall more than doubles in December; every category peaks at year-end",
subtitle="Monthly footfall index by category, baseline of 100 set by category mid-year average",
)
plt.show()
Axis Labels and Source Attribution¶
Add x_label/y_label when the axis dimensions need explicit naming (rather than relying on the column/index headers alone) and source_text for an attribution line beneath the chart on export-ready images. figsize lets you size the canvas to the matrix shape rather than relying on the default.
heatmap.plot(
hourly_traffic,
cbar_label="Visitors",
x_label="Day of week",
y_label="Hour",
figsize=(10, 6),
eyebrow="Foot traffic",
title="Saturday 6pm draws the heaviest foot traffic of the week",
subtitle="Hourly visitor counts by day of week",
source_text="Source: Door counter logs, Q4 2024",
)
plt.show()