Chapter 25 — Business Analytics and KPI Dashboards
Business analytics turns operational data into decisions. This chapter builds a synthetic orders dataset, computes core KPIs, performs cohort analysis, and assembles the elements of a KPI dashboard.
Learning Objectives
- Define and compute common business KPIs.
- Build an orders fact table from raw transactions.
- Analyze revenue by segment and over time.
- Perform a simple cohort (retention) analysis.
- Assemble a multi-panel KPI dashboard.
- Communicate findings to a business audience.
Prerequisites / Imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style='whitegrid')
1 Build an Orders Fact Table
We synthesize a year of orders across regions and products.
rng = np.random.default_rng(7)
n_days = 365
orders = pd.DataFrame({
'date': pd.date_range('2026-01-01', periods=n_days, freq='D'),
'region': rng.choice(['North','South','East','West'], n_days),
'product': rng.choice(['Widget','Gadget','Cable'], n_days, p=[0.5,0.3,0.2]),
'units': rng.integers(1, 20, n_days),
'unit_price': rng.choice([4.5, 12.75, 1.2], n_days),
})
orders['revenue'] = orders['units'] * orders['unit_price']
orders.head()
| date | region | product | units | unit_price | revenue | |
|---|---|---|---|---|---|---|
| 0 | 2026-01-01 | West | Gadget | 17 | 1.20 | 20.40 |
| 1 | 2026-01-02 | East | Cable | 2 | 4.50 | 9.00 |
| 2 | 2026-01-03 | East | Widget | 10 | 12.75 | 127.50 |
| 3 | 2026-01-04 | West | Widget | 2 | 12.75 | 25.50 |
| 4 | 2026-01-05 | East | Widget | 3 | 12.75 | 38.25 |
2 Core KPIs
Total revenue, average order value (AOV), daily orders, and total units.
kpis = {
'Total revenue ($)': round(float(orders['revenue'].sum()), 2),
'Average order value ($)': round(float(orders['revenue'].mean()), 2),
'Total units sold': int(orders['units'].sum()),
'Orders per day': round(float(len(orders)/n_days), 2),
}
for k, v in kpis.items():
print(f'{k}: {v}')
Total revenue ($): 23392.2 Average order value ($): 64.09 Total units sold: 3604 Orders per day: 1.0
3 Revenue by Segment
Group by product and region to find the best performers.
orders.groupby('product')['revenue'].agg(['sum','mean']).round(2)
| sum | mean | |
|---|---|---|
| product | ||
| Cable | 4243.50 | 63.34 |
| Gadget | 7136.55 | 58.98 |
| Widget | 12012.15 | 67.87 |
pivot = orders.pivot_table(index='region', columns='product', values='revenue', aggfunc='sum').round(0)
pivot
| product | Cable | Gadget | Widget |
|---|---|---|---|
| region | |||
| East | 1136.0 | 1999.0 | 3152.0 |
| North | 1096.0 | 1564.0 | 4041.0 |
| South | 758.0 | 1309.0 | 2471.0 |
| West | 1254.0 | 2265.0 | 2348.0 |
4 Revenue Over Time
Monthly revenue trend reveals seasonality and growth.
monthly = orders.set_index('date')['revenue'].resample('MS').sum()
plt.figure(figsize=(10,4))
monthly.plot()
plt.title('Monthly revenue'); plt.ylabel('revenue ($)')
plt.show()
5 Cohort Analysis
A cohort groups customers by their first-purchase month; retention is the share still active in later months. We approximate cohorts by joining month.
orders['month'] = orders['date'].dt.to_period('M')
orders['cohort'] = orders['date'].dt.to_period('M').astype(str)
cohort_sizes = orders.groupby('cohort').size()
print(cohort_sizes.head())
cohort 2026-01 31 2026-02 28 2026-03 31 2026-04 30 2026-05 31 dtype: int64
6 Retention Curve
We simulate repeat purchases over 12 monthly cohorts to illustrate a retention curve.
rng = np.random.default_rng(11)
months = pd.period_range('2026-01', periods=12, freq='M')
retention = []
for i, m in enumerate(months):
# retention decays from 100% over following months
decay = np.exp(-0.25*np.arange(12-i))
retention.append(np.round(decay*100, 1))
ret_df = pd.DataFrame(retention, index=[str(m) for m in months]).T
ret_df.iloc[:6, :6]
| 2026-01 | 2026-02 | 2026-03 | 2026-04 | 2026-05 | 2026-06 | |
|---|---|---|---|---|---|---|
| 0 | 100.0 | 100.0 | 100.0 | 100.0 | 100.0 | 100.0 |
| 1 | 77.9 | 77.9 | 77.9 | 77.9 | 77.9 | 77.9 |
| 2 | 60.7 | 60.7 | 60.7 | 60.7 | 60.7 | 60.7 |
| 3 | 47.2 | 47.2 | 47.2 | 47.2 | 47.2 | 47.2 |
| 4 | 36.8 | 36.8 | 36.8 | 36.8 | 36.8 | 36.8 |
| 5 | 28.7 | 28.7 | 28.7 | 28.7 | 28.7 | 28.7 |
Case Study: A KPI Dashboard
Combine the key visuals into a single multi-panel dashboard — the form a business stakeholder actually wants.
fig, axes = plt.subplots(2, 2, figsize=(13, 9))
# Top-left: monthly revenue
monthly.plot(ax=axes[0,0], color='steelblue'); axes[0,0].set_title('Monthly revenue')
# Top-right: revenue by product
rev_prod = orders.groupby('product')['revenue'].sum()
axes[0,1].bar(rev_prod.index, rev_prod.values, color='teal'); axes[0,1].set_title('Revenue by product')
# Bottom-left: units distribution
axes[1,0].hist(orders['units'], bins=20, color='coral', edgecolor='black'); axes[1,0].set_title('Units per order')
# Bottom-right: AOV by region
aov = orders.groupby('region')['revenue'].mean()
axes[1,1].bar(aov.index, aov.values, color='slateblue'); axes[1,1].set_title('AOV by region')
plt.tight_layout()
plt.show()
Exercises
- Compute total revenue and AOV for a synthetic orders dataset.
- Pivot revenue by region and product.
- Plot monthly revenue over a year.
- Define AOV and explain how it differs from total revenue.
- Build a 2x2 dashboard of four business charts.
- Compute each product's share of total revenue.
- Simulate 12 cohorts and plot a retention curve.
- Identify the top region by revenue and by AOV.
- Explain why cohort analysis matters for subscription businesses.
- Write a one-paragraph summary of findings for a manager.
Python Data Science: From Foundations to Applications — Chapter 25