Correlation vs causation, causal inference and time-series concepts
Why correlations mislead, how analysts get closer to causal answers without a perfect experiment, and the building blocks of time series — trend, seasonality, noise and autocorrelation.
This lesson builds on: Probability, sampling, confidence intervals, hypothesis tests and A/B testing.
- Identify confounding, reverse causality, selection bias and coincidence
- Describe causal methods: experiments, difference-in-differences, matched comparisons
- Decompose a time series into trend, seasonality and residual
- Explain autocorrelation and why it matters for forecasting and inference
Four ways a correlation misleads
| Trap | Example at Orion | What is really happening |
|---|---|---|
| Confounding | Stores with more staff sell more | Big stores have both more staff and more customers (size drives both) |
| Reverse causality | Marketing spend correlates with revenue | Spend is budgeted as a % of expected revenue |
| Selection bias | Customers who used cashback spend more | Heavy buyers are the ones who notice and use cashback |
| Coincidence / spurious trends | Two series both trending up over 3 years | Any two growing series correlate |
Getting closer to causation
- Randomised experiments (A/B tests) — the gold standard: randomisation balances confounders on average (previous lesson).
- Difference-in-differences (DiD) — compare the change in a treated group with the change in a similar untreated group over the same period. Assumes the groups would have followed parallel trends without treatment.
- Matched comparisons — compare treated units with untreated units that look similar on key characteristics (size, region, history).
- Regression with controls — include known confounders as predictors; only as good as the confounders you measured.
- Natural experiments / discontinuities — a rule creates as-good-as-random variation (e.g. eligibility cut-off).
Worked DiD example
A loyalty programme launched in Baku stores in March; other cities did not get it.
| Before (Jan–Feb avg) | After (Mar–Apr avg) | Change | |
|---|---|---|---|
| Baku stores (treated) | 100 | 118 | +18 |
| Other stores (control) | 80 | 90 | +10 |
Naive before/after for Baku: +18. But stores elsewhere grew +10 in the same period (seasonality, general growth). DiD estimate = 18 − 10 = +8 per store-day — the effect attributable to the programme, if trends would otherwise have been parallel (check pre-period trends!).
Time-series concepts
A time series is a sequence of observations ordered in time. Typical components:
- Trend — long-run direction (growth of ~12% a year at Orion Retail).
- Seasonality — patterns repeating with a fixed period (December peaks, weekend effects).
- Cycles — longer, irregular ups and downs (economic cycles).
- Residual / noise — what remains.
import pandas as pd, numpy as np
orders = pd.read_csv("retail/orders.csv", parse_dates=["order_date"])
items = pd.read_csv("retail/order_items.csv")
items["rev"] = items["quantity"] * items["unit_price"] * (1 - items["discount_pct"])
rev = items.merge(orders[["order_id", "order_date", "status"]], on="order_id")
m = rev[rev.status == "completed"].groupby(rev.order_date.dt.to_period("M"))["rev"].sum()
trend = m.rolling(12, center=True).mean()
seasonal_index = (m / trend).groupby(m.index.month).mean()
print("Seasonal index by month (1.00 = average month):")
print(seasonal_index.round(2).to_string())
lag1 = m.autocorr(1); lag12 = m.autocorr(12)
print(f"autocorrelation lag 1 = {lag1:.2f}, lag 12 = {lag12:.2f}")
Seasonal index by month (1.00 = average month):
order_date
1 0.96
2 0.71
3 1.02
4 0.95
5 1.07
6 1.02
7 1.04
8 0.96
9 0.90
10 0.91
11 1.10
12 1.40
autocorrelation lag 1 = 0.46, lag 12 = 0.91
The seasonal index shows December about 40% above an average month and February almost 30% below — the pattern you saw in SQL. The 12-month moving average isolates the trend. Autocorrelation (correlation of a series with its own past values) is high at lag 12: this December resembles last December. That is useful for forecasting (seasonal naive forecasts exploit it) and dangerous for naive statistics (observations are not independent).
"Revenue fell 30% in January" is mostly seasonality. Compare year-over-year, or seasonally adjust (divide by the seasonal index) before judging performance.
Practice
Customers who used cashback spent 2× more than others. Which explanation must be ruled out before claiming cashback caused higher spending?
Treated stores: before 200, after 236 (daily orders). Control stores: before 150, after 165. What is the difference-in-differences estimate?
Monthly revenue has a lag-12 autocorrelation of 0.91. What does that mean?
Summary
- Correlation can come from confounding, reverse causality, selection or coincidence.
- Experiments, DiD, matching and controls move analyses toward causal conclusions — each with assumptions to check.
- Time series = trend + seasonality (+ cycles) + noise; autocorrelation makes the past informative but breaks independence assumptions.