Cohort Plot Gallery¶
Cohort plots visualise how groups of customers behave over time as a colour-coded grid: rows are cohorts (acquisition month, signup quarter), columns are periods since acquisition, and cells show the metric. The triangular shape comes from newer cohorts having fewer observed periods.
Cohort plots excel at:
- Retention curves: read the decay of each cohort across the row
- Cohort comparison: scan a column to compare cohorts at the same age
- Promotion or seasonality effects: spot which acquisition periods produced stickier customers
- Revenue contribution: track per-customer spend as cohorts mature
import matplotlib.pyplot as plt
import pandas as pd
from openretailscience.plots import cohort
Basic Retention Cohort¶
The default call: pass a wide-format DataFrame where the index is the cohort and the columns are periods since acquisition. Cells render as percentages by default (percentage=True), and column labels render at the top of the matrix to read naturally as a left-to-right time progression alongside the cohort labels.
cohort.plot(
retention_data,
cbar_label="Retention rate",
eyebrow="Retention",
title="December 2024 cohort retains the highest at every observed month",
subtitle="% of original cohort still active by months since acquisition",
figsize=(10, 6),
)
plt.show()
Revenue Cohort¶
Set percentage=False to render raw values (rather than percentages) in each cell. Use this shape for any metric that isn't a rate, e.g. revenue per customer, orders per cohort, or average order value.
Internally this just swaps the cell format from "{x:.0%}" to "{x:g}", which trims trailing zeros for a cleaner look.
cohort.plot(
revenue_per_customer,
cbar_label="Revenue per customer ($)",
percentage=False,
eyebrow="Cohort revenue",
title="December 2024 cohort spends $78 per active customer at month 1, the highest of any cohort",
subtitle="Average revenue per active customer ($) by cohort and tenure",
figsize=(10, 6),
)
plt.show()
Continuous Colormap¶
Pass colormap_style="continuous" to render the cohort grid with a smooth colour gradient instead of the default 5-bin stepped scale. Useful when retention differences between cohorts are small enough that the discrete bins lump them together.
cohort.plot(
retention_data,
cbar_label="Retention rate",
colormap_style="continuous",
eyebrow="Retention",
title="Continuous gradient surfaces small retention differences between cohorts",
subtitle="Same retention data, smooth colormap rather than stepped bins",
figsize=(10, 6),
)
plt.show()
Axis Labels and Source Attribution¶
Add x_label/y_label when the axis dimensions need explicit naming alongside the column and index headers, and source_text for an attribution line on export-ready images.
cohort.plot(
retention_data,
cbar_label="Retention rate",
x_label="Months since acquisition",
y_label="Acquisition cohort",
eyebrow="Retention",
title="Retention decays sharply in the first three months, then flattens",
subtitle="% of original cohort still active by months since acquisition",
source_text="Source: CRM activity logs, Aug 2024 to Apr 2025",
figsize=(10, 6),
)
plt.show()