Day 28. Frisch–Waugh–Lovell & Partialling Out
What "controlling for" really does. Every multiple-regression coefficient is a simple regression on residualised data.
- ●State and prove the Frisch–Waugh–Lovell (FWL) theorem.
- ●Compute a multiple-regression coefficient by partialling out, and read it from an added-variable plot.
- ●Show that fixed-effects (within) estimators are FWL applied to group dummies.
- ●Explain how OLS with controls weights heterogeneous treatment effects, and preview partialling out with machine learning.
Theory
The theorem
Split the regressors: . Let , the residual-maker for (Day 20). Define the residualised variables
FWL theorem. The OLS coefficient on in the full regression equals the coefficient from regressing on :
and the residuals of the two regressions are identical.
What it means
"Controlling for " means: strip out of both and everything linearly predictable from , then relate what is left. For a single regressor this is the regression anatomy formula
Consequences you will use repeatedly:
- Fixed effects: with = group dummies, subtracts group means, so the within (demeaned) regression gives the same slope as including the dummies.
- Precision: , and , giving the VIF of Day 18.
- Added-variable plot: scatter against ; the fitted slope is .
- Double machine learning (Day 90) replaces the linear projections with flexible machine-learning predictions: residualise and the treatment on , then regress residual on residual.
Part 1 · Warm-up
Exercise 1 · What M₂ does
In words, what is ?
Show solution
The residuals from regressing each column of on : the part of that cannot linearly explain.
Exercise 2 · The intercept is partialled out too
Show that the slope in equals the slope from regressing demeaned on demeaned without an intercept.
Show solution
Take : is the centring matrix, so and . FWL gives , the Cov/Var formula.
Exercise 3 · Partialling out by hand
Four workers: marks urban residence, is years of post-secondary schooling and is hourly earnings (in $10). Regress earnings on an intercept, schooling and the urban dummy. Compute the schooling coefficient by FWL.
Show solution
Step 1. Partialling out means subtracting the rural and urban means (FWL with group dummies).
Step 2. Schooling means: rural , urban . So .
Step 3. Earnings means: rural , urban . So .
Step 4. Residual-on-residual slope:
Answer: each extra year of schooling goes with $14/hour more earnings within the same area.
Exercise 4 · The short regression
For the same data, compute the slope from regressing on alone (with an intercept).
Show solution
Step 1. Means: and .
Step 2. Deviations: and .
Step 3. Cross-product ; squared deviations .
Step 4. Slope .
Answer: 1.83 without the urban control versus 1.40 with it: part of schooling's raw association with earnings is the urban premium.
Exercise 5 · Only one side needs residualising
Show that .
Show solution
Step 1. , since is symmetric and idempotent.
Step 2. So regressing raw on gives the same coefficient (but not the same residuals or SEs).
Part 2 · Proofs
Exercise 6 · Proving FWL
Prove the FWL theorem.
Show solution
Step 1. Write the full OLS fit: , with and (Day 20).
Step 2. Multiply through by . , and because is already orthogonal to ():
Step 3. Pre-multiply by : .
Step 4. (Step 1).
Step 5. So .
Exercise 7 · Identical residuals
Show that the residuals from regressing on equal the full-regression residuals .
Show solution
From Exercise 6, . So is the same, but the residualised regression should still use (all regressors), not , when computing .
Exercise 8 · Regression anatomy
For a single regressor , show .
Show solution
Step 1. By FWL and Exercise 5, .
Step 2. If includes an intercept, has mean zero, so , i.e. times the sample covariance; the denominator is times the variance.
Exercise 9 · Orthogonal controls change nothing
Prove that if , adding leaves unchanged.
Show solution
Step 1. .
Step 2. FWL then gives , the short-regression coefficient.
Step 3. Randomised treatments are (approximately) orthogonal to pre-treatment covariates, which is why adding covariates changes the point estimate little while improving precision (Day 27).
Exercise 10 · Fixed effects are FWL
Show that including a full set of group dummies is equivalent to demeaning and by group.
Show solution
Step 1. With (no separate intercept), and stacks group sums, so replaces each by its group mean.
Step 2. Hence and likewise for ; FWL gives the within estimator.
Part 3 · Applied
Exercise 11 · Interpreting the change
In Exercises 3–4 the coefficient on falls from 1.83 to 1.40 when is added. Explain using the OVB formula.
Show solution
Step 1. Urban workers have more schooling (group means 4 versus 1.5).
Step 2. Urban residence raises earnings at a given schooling level (the full regression gives a coefficient of 1.5 on the dummy, i.e. $15/hour).
Step 3. Omitting it loads part of the urban premium onto schooling: OVB = (effect of urban) × (slope of urban on schooling) > 0.
Answer: the drop from 1.83 to 1.40 removes that bias, provided urban residence is a confounder. If schooling caused people to move to cities (a mediator), controlling for it would instead remove part of schooling's effect.
Exercise 12 · Two-way fixed effects
In a balanced panel, show that partialling out unit and time dummies transforms into .
Show solution
Step 1. Projecting on unit dummies replaces by the unit mean ; projecting on time dummies replaces it by the period mean .
Step 2. In a balanced panel the two sets of dummies are orthogonal once the overall mean is removed, so the projection onto both adds the two parts and subtracts the grand mean once (otherwise it would be counted twice): .
Step 3. The residual is .
Answer: two-way FE = double demeaning. With unbalanced panels or staggered treatment this simple form fails, part of the story of Day 70.
Exercise 13 · OLS weights heterogeneous effects by treatment variance
Two strata of equal size have treatment effects 1 and 3. The treatment probability is 0.5 in stratum A and 0.1 in stratum B. Regressing on and stratum dummies gives approximately with . Compute it and compare with the ATE.
Show solution
Step 1. Conditional treatment variances: stratum A ; stratum B .
Step 2. Weights (equal stratum sizes): , .
Step 3. Regression estimate: .
Step 4. ATE: .
Answer: 1.53 versus 2. With heterogeneous effects, OLS with controls estimates a variance-weighted average (Angrist, 1998), favouring strata where treatment is closest to 50/50.
Exercise 14 · Partialling out with machine learning: 401(k) eligibility
To estimate the effect of 401(k) eligibility on household savings , controlling flexibly for income, age and education , double ML assumes and regresses on , with both predictions from machine learning. Why is this FWL?
Show solution
Step 1. FWL removes from and everything linearly predictable from the controls, then regresses residual on residual.
Step 2. Here the linear projection is replaced by the conditional expectation , estimated flexibly (e.g. random forests), so need not be linear.
Step 3. The residualised is the variation in eligibility not explained by income, age and education; its relation to residualised savings identifies .
Answer: it is FWL with machine-learning projections (Robinson, 1988; Day 90).
Exercise 15 · An added-variable plot
Why can an added-variable plot reveal an influential observation that a raw scatter of against hides?
Show solution
Step 1. By FWL, depends only on the residualised data .
Step 2. A unit can look ordinary in raw yet be unusual given (a large ), which gives it high leverage on .
Step 3. A raw scatter of on hides this; the added-variable plot of against shows it.
Answer: the added-variable plot shows the data the coefficient actually uses (see the FWL simulator).
Verify in Python
import numpy as np
x2 = np.array([0, 0, 1, 1.]); x1 = np.array([1, 2, 3, 5.]); y = np.array([2, 3, 6, 9.])
X = np.column_stack([np.ones(4), x1, x2])
b_full = np.linalg.lstsq(X, y, rcond=None)[0]
X2 = np.column_stack([np.ones(4), x2]); M2 = np.eye(4) - X2 @ np.linalg.pinv(X2)
x1t, yt = M2 @ x1, M2 @ y
print("full regression:", b_full.round(4))
print("FWL slope:", round(x1t @ yt / (x1t @ x1t), 4), " raw y on residualised x1:", round(x1t @ y / (x1t @ x1t), 4))
print("short regression slope:", round(np.polyfit(x1, y, 1)[0], 4))
e_full = y - X @ b_full; e_fwl = yt - x1t * (x1t @ yt / (x1t @ x1t))
print("same residuals:", np.allclose(e_full, e_fwl))
# Variance-weighted effects (Exercise 13)
rng = np.random.default_rng(28); n = 400_000
s = rng.random(n) < 0.5 # stratum B
p = np.where(s, 0.1, 0.5); T = rng.random(n) < p
Y = np.where(s, 5, 0) + np.where(s, 3, 1) * T + rng.normal(size=n)
Z = np.column_stack([np.ones(n), T, s])
print("regression estimate:", np.linalg.lstsq(Z, Y, rcond=None)[0][1].round(3), " ATE: 2")
Key takeaways
- A multiple-regression coefficient is a simple regression of residualised on residualised .
- Fixed effects, demeaning and "controlling for" are all FWL.
- With heterogeneous effects, OLS with controls weights strata by the conditional variance of treatment, not by population share.
Simulation Lab: Partialling Out (FWL)
Open full screen →A confounded scatter beside its added-variable plot: the residual-on-residual slope equals the multiple-regression coefficient.
Left: raw y against x₁; the naive slope absorbs the effect of the confounder x₂. Right: the added-variable plot, residuals of y on x₂ against residuals of x₁ on x₂. Its slope is exactly the multiple-regression coefficient (true value 1).