AI-220 · Lesson 11 of 12 · 26 min

Metrics, dashboards and experiments

Lesson 10 covered how to make individual charts honest and clear. Much of the data work in organizations, however, goes into recurring products: metrics that track how a product, process or model is doing, dashboards that display them, and experiments that test whether a change made things better. Each has characteristic traps. A metric can be defined in two reasonable ways that disagree; a dashboard can show many numbers and answer no question; an experiment can declare a winner that is noise. This lesson covers how to define metrics precisely, how to design dashboards that support decisions, the paradoxes of aggregated data, and the statistics and practice of A/B testing.

Defining a metric

A metric is a number computed the same way every time, so that changes in it reflect changes in the world rather than in the calculation. A good metric definition states:

  • The numerator and denominator, with exact inclusion rules (which events, which users, which statuses).
  • The unit of analysis: per user, per session, per order, per day.
  • The time window and time zone.
  • How missing data, test accounts, bots, refunds and duplicates are handled.
  • The owner, and where the calculation lives (one shared definition in code or a metrics layer, not reimplemented in each dashboard).

Ratio metrics

Many metrics are ratios: conversion rate, click-through rate, error rate. A ratio can be computed as the mean of per-unit ratios or as the ratio of totals, and the two answer different questions.

The mean of per-user conversion rates and the ratio of total orders to total sessions differ by almost three times, because one heavy user has many sessions and a low rate.
import pandas as pd

# Sessions and conversions per user for one week
users = pd.DataFrame({
    "user": ["a", "b", "c", "d", "e"],
    "sessions": [1, 1, 2, 40, 6],
    "orders": [1, 0, 1, 4, 0],
})
users["rate"] = users["orders"] / users["sessions"]

mean_of_ratios = users["rate"].mean()
ratio_of_sums = users["orders"].sum() / users["sessions"].sum()
print(users.to_string(index=False))
print(f"mean of per-user rates : {mean_of_ratios:.3f}  (each user counts equally)")
print(f"total orders / sessions: {ratio_of_sums:.3f}  (each session counts equally)")
Output
user  sessions  orders  rate
   a         1       1   1.0
   b         1       0   0.0
   c         2       1   0.5
   d        40       4   0.1
   e         6       0   0.0
mean of per-user rates : 0.320  (each user counts equally)
total orders / sessions: 0.120  (each session counts equally)

The mean of ratios weights every user equally, which suits questions about the typical user. The ratio of totals weights every session equally, which suits questions about the business as a whole. Neither is wrong, but a metric must say which it is, and the two should never be compared with each other.

Leading, lagging and guardrail metrics

Organizations usually track a small hierarchy of metrics:

  • A north-star or primary metric that reflects the value delivered, such as weekly active customers who complete a purchase.
  • Leading indicators that move sooner and predict it, such as sign-ups or first-week engagement.
  • Guardrail metrics that must not get worse, such as latency, error rates, complaints, refunds, and fairness measures across groups.

Any metric that becomes a target can be gamed, consciously or not (Goodhart's law): a support team measured on ticket closure time may close tickets prematurely. Guardrails and periodic review of what a metric actually rewards are the defences.

Simpson's paradox

Aggregating across groups can reverse a relationship that holds within every group. This is Simpson's paradox, and it appears whenever the groups differ in size between the things being compared and also differ in their rates.

Model B approves a higher share of applicants in both segments, but a lower share overall, because it saw mostly new applicants, who are approved less often.
import pandas as pd

# Approval rates for two models, by applicant segment
rows = [
    ("model A", "new", 300, 240), ("model A", "existing", 700, 665),
    ("model B", "new", 800, 680), ("model B", "existing", 200, 194),
]
df = pd.DataFrame(rows, columns=["model", "segment", "applicants", "approved"])
df["rate"] = (df["approved"] / df["applicants"]).round(3)
print(df.pivot(index="segment", columns="model", values="rate"))

overall = df.groupby("model")[["applicants", "approved"]].sum()
overall["rate"] = (overall["approved"] / overall["applicants"]).round(3)
print(overall)
Output
model     model A  model B
segment
existing     0.95     0.97
new          0.80     0.85
         applicants  approved   rate
model
model A        1000       905  0.905
model B        1000       874  0.874

Model B is better within each segment, but most of its applicants were new customers, who have lower approval rates whatever the model; model A saw mostly existing customers. The overall comparison mixes the effect of the model with the effect of the mix. When groups differ in composition, compare within groups, or adjust for the composition (standardize to a common mix), and ask which comparison answers the decision at hand. Randomized experiments avoid the problem by making the groups alike.

Bar chart illustrating Simpson's paradox. For new applicants, model B's approval rate of 85% is higher than model A's 80%. For existing applicants, model B's 97% is higher than model A's 95%. But the overall bars show model A at 90.5% and model B at 87.4%. Below the bars, the mix of applicants is shown: model A saw 30% new and 70% existing; model B saw 80% new and 20% existing.
Simpson's paradox: B wins in every segment but loses overall, because of the mix of applicants.

Dashboards that support decisions

A dashboard is a set of charts and numbers that people check repeatedly. Good dashboards are designed backwards from the decisions they support:

  • Purpose: who uses it, how often, and what they will do when a number changes. A dashboard for an operations team watching a data centre every minute differs from a monthly executive summary.
  • Hierarchy: the few most important numbers at the top, with context (target, previous period, trend), and detail below for diagnosis.
  • Comparisons: every number shown with something to compare it to, such as last week, the same week last year, a target or a forecast range. A number on its own cannot be judged.
  • Consistency: shared metric definitions, the same time zone and period across charts, the same colours for the same categories.
  • Freshness and quality: when the data was last updated, and a visible warning when a pipeline is late or a data quality check has failed (Lesson 8).
  • Restraint: fewer charts, each answering a question. Dashboards accumulate charts that nobody uses; review and remove them.

Worked problem

Is this change real?

A daily conversion rate is usually 4.8%, with a day-to-day standard deviation of 0.3 percentage points. Today it is 4.2%. How unusual is this, and what should the dashboard do?

Show solution
  1. Difference: \(4.2 - 4.8 = -0.6\) points, which is \(-0.6/0.3 = -2\) standard deviations.
  2. A move of 2 standard deviations happens on about 5% of days by chance, roughly once in three weeks.

Answer: Somewhat unusual but not alarming on its own. A good dashboard shows the expected range (for example a band of ±2 standard deviations, adjusted for weekday) so people do not react to noise, and alerts only on larger or sustained deviations, or on several related metrics moving together.

A/B testing

The most reliable way to learn whether a change causes an improvement is a randomized controlled experiment, called an A/B test in product and model work. Users (or sessions, stores, regions) are randomly assigned to control (A) or treatment (B), and the metric is compared. Randomization makes the groups alike in everything except the change, on average, so a difference beyond what chance explains can be attributed to the change.

Steps in a well-run test:

  • State the hypothesis, the primary metric, guardrails, and the minimum effect worth detecting, before starting.
  • Calculate the sample size needed, and the duration, including whole weeks to cover weekly cycles.
  • Randomize at the right unit: if users see the change across sessions, randomize by user, and analyse by user.
  • Check the split: the share of units in each group should match the design (a sample ratio mismatch signals a bug).
  • Run for the planned duration, then analyse once.
A two-proportion z-test and a confidence interval for a checkout change, and the sample sizes needed to detect smaller effects.
import math
from scipy.stats import norm

# A/B test of a checkout change: conversions out of visitors
n_a, x_a = 24_000, 1_152      # control
n_b, x_b = 24_000, 1_272      # treatment
p_a, p_b = x_a / n_a, x_b / n_b
p = (x_a + x_b) / (n_a + n_b)
se0 = math.sqrt(p * (1 - p) * (1 / n_a + 1 / n_b))
z = (p_b - p_a) / se0
p_value = 2 * (1 - norm.cdf(abs(z)))
se = math.sqrt(p_a * (1 - p_a) / n_a + p_b * (1 - p_b) / n_b)
lo, hi = (p_b - p_a) - 1.96 * se, (p_b - p_a) + 1.96 * se
print(f"control {p_a:.4f}, treatment {p_b:.4f}, lift {100 * (p_b / p_a - 1):.1f}%")
print(f"z = {z:.2f}, p = {p_value:.4f}, 95% CI for difference [{lo:.4f}, {hi:.4f}]")

# Sample size per group to detect a 0.5 point change from 4.8% with 80% power
def n_per_group(p0, delta, alpha=0.05, power=0.8):
    za, zb = norm.ppf(1 - alpha / 2), norm.ppf(power)
    p1 = p0 + delta
    return math.ceil((za + zb) ** 2 * (p0 * (1 - p0) + p1 * (1 - p1)) / delta ** 2)

for delta in (0.010, 0.005, 0.0025):
    print(f"detect +{100 * delta:.2f} points: {n_per_group(0.048, delta):,} per group")
Output
control 0.0480, treatment 0.0530, lift 10.4%
z = 2.50, p = 0.0124, 95% CI for difference [0.0011, 0.0089]
detect +1.00 points: 7,875 per group
detect +0.50 points: 30,105 per group
detect +0.25 points: 117,603 per group

The test found a 0.5 point increase in conversion (a 10.4% relative lift), with a 95% confidence interval from 0.11 to 0.89 points: the change very likely helps, but the true size of the effect is uncertain by a factor of eight. The sample-size calculation shows the cost of detecting small effects: halving the detectable effect roughly quadruples the users needed, because the standard error falls only with the square root of the sample size.

\[n \approx \frac{(z_{1-\alpha/2} + z_{1-\beta})^{2}\,[p_0(1-p_0) + p_1(1-p_1)]}{\delta^{2}}\]

Peeking and other pitfalls

The most common error in practice is checking results every day and stopping as soon as the difference looks significant. Each look is another chance for noise to cross the threshold, so the real false-positive rate is far above the nominal 5%.

Two thousand simulated A/A tests with no real difference: testing once gives about the intended 5% false positives; peeking daily and stopping at the first significant result gives more than 20%.
import numpy as np
from scipy.stats import norm

# A/A tests: both groups identical, so every "significant" result is a false positive
rng = np.random.default_rng(11)
experiments, days, per_day, p = 2000, 20, 500, 0.05
peek_hits = final_hits = 0
for _ in range(experiments):
    a = rng.binomial(per_day, p, days).cumsum()
    b = rng.binomial(per_day, p, days).cumsum()
    n = per_day * np.arange(1, days + 1)
    pooled = (a + b) / (2 * n)
    z = (b - a) / n / np.sqrt(pooled * (1 - pooled) * 2 / n)
    sig = np.abs(z) > norm.ppf(0.975)
    peek_hits += sig.any()          # stop at the first day that looks significant
    final_hits += sig[-1]           # test once, at the planned end
print(f"false positive rate, test once at the end: {final_hits / experiments:.3f}")
print(f"false positive rate, peek every day      : {peek_hits / experiments:.3f}")
Output
false positive rate, test once at the end: 0.045
false positive rate, peek every day      : 0.236

Solutions are to fix the duration in advance and analyse once, or to use methods designed for continuous monitoring, such as sequential tests with adjusted thresholds or always-valid confidence intervals, which many experimentation platforms provide. Other pitfalls:

  • Many metrics and segments: testing 20 metrics at 5% will usually find one "significant" by chance. Name one primary metric and correct for multiple comparisons when exploring.
  • Novelty and learning effects: users react to anything new at first; effects can fade or grow over weeks.
  • Interference: when units affect each other (a ride-sharing market, a social network, shared inventory), treatment spills into control, and randomization by region or time is needed.
  • Practical significance: a statistically significant effect may be too small to matter, and a large effect may be uncertain. Report the effect size and its interval, not only the p-value.

Testing models

A new machine learning model is evaluated offline on held-out data (Lesson 6 covered honest splits), but offline metrics do not always predict business outcomes. Online A/B tests compare models on the real metric, with guardrails on latency, errors and fairness. Shadow deployment, running the new model alongside the old without acting on its output, is a lower-risk step before an A/B test, and catches errors in features and serving (Lesson 12).

Common mistakes

  • MistakeComparing a mean-of-ratios metric with a ratio-of-totals metric.

    InsteadDefine which one a metric is, and compare like with like.

  • MistakeComparing overall rates when the group mix differs.

    InsteadCompare within groups or standardize the mix; randomize when possible.

  • MistakeShowing numbers with no comparison.

    InsteadShow targets, previous periods or expected ranges alongside every number.

  • MistakeStopping an A/B test when it first looks significant.

    InsteadFix the duration in advance or use a sequential method.

  • MistakeReporting only a p-value.

    InsteadReport the effect size with its confidence interval, and check guardrails.

Summary and key terms

  • A metric definition fixes numerator, denominator, unit, window, exclusions and owner.
  • Mean of ratios and ratio of totals answer different questions.
  • Primary, leading and guardrail metrics work together; targets invite gaming.
  • Simpson's paradox: aggregate comparisons can reverse group comparisons when mixes differ.
  • Dashboards serve decisions: hierarchy, comparisons, consistency, freshness and restraint.
  • A/B tests need a planned sample size, the right unit, one analysis or sequential methods, and effect sizes with intervals.
Metric
A precisely defined number tracked over time.
Ratio of totals
Sum of numerators divided by sum of denominators.
Guardrail metric
A metric that must not deteriorate when optimizing another.
Goodhart's law
A measure that becomes a target ceases to be a good measure.
Simpson's paradox
A reversal of a relationship when groups are combined.
A/B test
A randomized experiment comparing control and treatment.
Statistical power
The probability of detecting an effect of a given size.
Sample ratio mismatch
An unexpected imbalance in group sizes, signalling a bug.
Peeking
Repeatedly testing and stopping at the first significant result.
Shadow deployment
Running a new model alongside the old without acting on its output.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. Users: 1 order in 2 sessions, and 1 order in 8 sessions. Mean of ratios and ratio of totals?

    Show answer

    0.3125 and 0.2.

  2. Which suits "how does the typical user convert?"

    Show answer

    Mean of per-user ratios.

  3. Give an example of a guardrail metric.

    Show answer

    Latency, error rate, refunds or complaints.

  4. What causes Simpson's paradox?

    Show answer

    Different group mixes combined with different group rates.

  5. A metric is 1.5 standard deviations below normal. Alert?

    Show answer

    Usually not; it happens often by chance.

  6. Why randomize by user rather than session when users see the change across sessions?

    Show answer

    Sessions of one user are not independent and may see both versions.

  7. Halving the detectable effect multiplies the sample size by about?

    Show answer

    4.

  8. Control 5.0% of 10,000; treatment 5.6% of 10,000. Difference?

    Show answer

    0.6 points, a 12% lift.

  9. Why does peeking inflate false positives?

    Show answer

    Each look is another chance for noise to cross the threshold.

  10. What does shadow deployment test?

    Show answer

    A new model's outputs and serving in production without acting on them.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz