Instrumental Variables: Concept and Applications
Learning Objectives
By the end of this module, you will be able to:
- Diagnose endogeneity in regression models and explain why OLS fails in its presence
- Distinguish the three sources of endogeneity: omitted variables, measurement error, and simultaneity
- Judge whether a candidate instrument satisfies relevance and exogeneity conditions
- Implement Two-Stage Least Squares (2SLS) in Python using
linearmodels - Test for weak instruments using first-stage F-statistics and Stock-Yogo critical values
- Perform overidentification tests (Hansen J-test) when multiple instruments are available
- Interpret IV results and write them up for a journal article
Setup & Prerequisites
Ensure you have the required libraries installed:
pip install pandas numpy statsmodels linearmodels matplotlib seaborn
We use the Mroz dataset (available in statsmodels) throughout this module — the same dataset from Module 1. This ensures continuity and lets you focus on the IV technique rather than learning new data.
In This Module
1. The Endogeneity Problem — Why OLS Can Fail
Research Question
"Does an additional year of education cause higher wages?" This is perhaps the most studied question in labour economics. The problem: education is not randomly assigned. People who choose more education may differ systematically from those who don't — they may have higher ability, more motivation, or wealthier families. These unobserved factors also affect wages. OLS conflates the causal effect of education with these selection effects.
Intuition
Endogeneity means your explanatory variable is correlated with the error term: Cov(X, ϵ) ≠ 0. When this happens, OLS is no longer unbiased or consistent — your estimate does not converge to the true value even with infinite data. The OLS coefficient absorbs part of the error term's effect, producing a biased estimate.
Think of it this way: OLS compares the wages of people with 16 years of education to those with 12 years, and attributes the entire difference to education. But the 16-year group also has higher average ability. OLS gives education credit for ability's contribution. The IV estimator uses an instrument — something that affects education but is unrelated to ability — to isolate the portion of education variation that is "as good as random."
The Three Sources of Endogeneity
1. Omitted Variable Bias
The most common source. A variable that affects both X and Y is left out of the regression. Example: "Ability" affects both how much education you get and how much you earn. If ability is not in the wage equation, education "steals" its coefficient.
Direction of bias: In the wage-education example, ability positively affects both education and wages, so OLS overestimates the return to education (upward bias).
2. Measurement Error (Errors-in-Variables)
When your X variable is measured with noise, OLS coefficients are attenuated — biased toward zero. Example: Survey respondents misreport their years of education. The noisy measure dilutes the true relationship.
Classical measurement error in X biases the coefficient toward zero (attenuation bias). Measurement error in Y does not cause endogeneity — it just increases standard errors.
3. Simultaneity (Reverse Causality)
X causes Y, but Y also causes X. Example: More police officers may reduce crime (causal effect of interest), but cities with higher crime rates hire more police (reverse causality). The observed correlation mixes both directions.
Another example: Higher advertising spending may increase sales, but firms with higher sales can afford more advertising. OLS cannot disentangle the two directions.
2. What Makes a Valid Instrument?
Research Question
"Can I use parents' education as an instrument for a person's own education to estimate the causal return to schooling?"
Intuition
An instrument Z is a variable that provides exogenous variation in the endogenous regressor X. For Z to be valid, it must satisfy two conditions that cannot both be fully tested — one must be argued theoretically:
Two Conditions for a Valid Instrument
(Relevance — testable)
(Exogeneity — argued, not fully tested)
Condition 1: Relevance (Instrument Relevance)
The instrument must be strongly correlated with the endogenous variable. This is testable: in the first-stage regression of X on Z, the coefficient on Z must be statistically significant. The rule of thumb: the first-stage F-statistic should exceed 10. Below 10, you have a weak instrument problem (Section 4).
For our example: Parental education is correlated with a person's own education — more educated parents tend to have more educated children. This is testable and generally holds strongly in survey data.
Condition 2: Exogeneity (Exclusion Restriction)
The instrument must be uncorrelated with the error term in the structural equation. In other words, Z affects Y only through X. There is no direct path from Z to Y, and Z is not correlated with any omitted variable that affects Y.
For our example: Does father's education affect a person's wages only through the person's own education? Or does it also affect wages through family connections, inherited wealth, or genetic ability? This is the crux of the IV debate — and it cannot be proven statistically. You must make a theoretical argument.
When to Use
- You have a clearly endogenous regressor and a plausible instrument
- Random assignment is infeasible (observational data)
- You can make a credible theoretical case for the exclusion restriction
- You have a large enough sample — IV estimators are consistent but can have large standard errors
When NOT to Use
- Your instrument is weak (first-stage F < 10) — 2SLS will be more biased than OLS
- You cannot defend the exclusion restriction — a bad instrument is worse than no instrument
- Your sample is very small — IV standard errors are larger than OLS standard errors
- You have a valid natural experiment (difference-in-differences or RDD may be more appropriate)
- The endogenous variable is actually exogenous — test with a Hausman endogeneity test first
3. Two-Stage Least Squares — Mechanics and Intuition
Intuition
2SLS does exactly what its name suggests: it runs two regressions. The first stage isolates the variation in X that is driven by the instrument Z — variation that is, by construction, uncorrelated with the error term. The second stage uses this "cleaned" version of X to estimate the relationship with Y.
Think of it as a filter. X has two components: a "good" part (driven by Z, exogenous) and a "bad" part (driven by unobserved confounders, endogenous). The first stage extracts the good part. The second stage estimates the effect of the good part on Y. Because Z is exogenous, the good part of X is also exogenous.
The Two Stages
Structural equation (the relationship we care about):
Yi = β0 + β1 Xi + ϵi — but Cov(Xi, ϵi) ≠ 0
First stage: Regress X on Z (and any exogenous controls W):
Xi = π0 + π1 Zi + π2 Wi + ui
Obtain predicted values: Ō = π̂0 + π̂1 Zi + π̂2 Wi
Second stage: Regress Y on predicted X (and controls W):
Yi = β0 + β1 Ōi + β2 Wi + ηi
The coefficient β̂1 from the second stage is the 2SLS estimator. Because Ō is constructed from Z (exogenous) and W (exogenous), it is uncorrelated with ϵ, and β̂1 is consistent.
linearmodels.iv.IV2SLS handles the correction automatically.Python Implementation
# ── Load data ──────────────────────────────────────────────────────
import pandas as pd
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf
from linearmodels.iv import IV2SLS
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('seaborn-v0_8-darkgrid')
# Load the Mroz dataset
df = sm.datasets.get_rdataset("mroz", "wooldridge").data
df = df.dropna(subset=['lwage']) # Working women only
# Quick inspection
print(f"Observations: {len(df)}")
print(df[['lwage', 'educ', 'exper', 'expersq', 'fatheduc', 'motheduc']].describe())
# ── Step 0: Run OLS (for comparison) ──────────────────────────────
ols_model = smf.ols("lwage ~ educ + exper + expersq", data=df).fit()
print("\n========== OLS RESULTS ==========")
print(ols_model.summary())
OLS Regression Results
==============================================================================
Dep. Variable: lwage R-squared: 0.145
No. Observations: 428 F-statistic: 23.98
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
Intercept -0.3799 0.249 -1.527 0.128 -0.869 0.109
educ 0.1079 0.014 7.547 0.000 0.080 0.136
exper 0.0406 0.013 3.058 0.002 0.015 0.067
expersq -0.0007 0.000 -1.770 0.077 -0.002 0.000
==============================================================================
OLS says each year of education raises wages by ~10.8%. But if education is endogenous (women with higher ability get more education AND earn higher wages), this estimate is biased upward.
Step 1: First-Stage Regression
# ── First stage: Regress education on instruments + controls ──────
first_stage = smf.ols("educ ~ fatheduc + motheduc + exper + expersq", data=df).fit()
print("========== FIRST STAGE ==========")
print(first_stage.summary())
# Extract the first-stage F-statistic for the instruments
# H0: coefficients on fatheduc and motheduc are jointly zero
from statsmodels.stats.anova import anova_lm
restricted = smf.ols("educ ~ exper + expersq", data=df).fit()
f_test_result = anova_lm(restricted, first_stage)
print(f"\nJoint F-test for instruments (fatheduc, motheduc):")
print(f_test_result)
OLS Regression Results
==============================================================================
Dep. Variable: educ R-squared: 0.215
No. Observations: 428 F-statistic: 28.94
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
Intercept 8.2115 0.563 14.573 0.000 7.104 9.319
fatheduc 0.1905 0.029 6.583 0.000 0.134 0.247
motheduc 0.1509 0.034 4.465 0.000 0.084 0.217
exper -0.0454 0.045 -1.013 0.312 -0.134 0.043
expersq 0.0010 0.001 0.768 0.443 -0.002 0.004
==============================================================================
Joint F-test for instruments (fatheduc, motheduc):
F-statistic = 42.83, p-value = 0.0000
The first-stage F-statistic is 42.83 — well above 10. Both parental education variables are individually significant and jointly highly significant. We have strong instruments.
Step 2: 2SLS Estimation
# ── 2SLS using linearmodels ───────────────────────────────────────
# Formula syntax: depvar ~ controls + [endog_var ~ instruments]
iv_model = IV2SLS.from_formula(
"lwage ~ 1 + exper + expersq + [educ ~ fatheduc + motheduc]",
data=df
)
iv_results = iv_model.fit(cov_type='robust')
print("========== 2SLS RESULTS ==========")
print(iv_results.summary)
# ── Compare OLS vs 2SLS ──────────────────────────────────────────
print("\n========== COMPARISON: OLS vs 2SLS ==========")
print(f"{'':<15} {'OLS':>10} {'2SLS':>10}")
print(f"{'educ':<15} {ols_model.params['educ']:>10.4f} {iv_results.params['educ']:>10.4f}")
print(f"{'SE(educ)':<15} {ols_model.bse['educ']:>10.4f} {iv_results.std_errors['educ']:>10.4f}")
IV2SLS Estimation Summary
==============================================================================
Dep. Variable: lwage R-squared: 0.1357
Estimator: IV2SLS Adj. R-squared: 0.1275
No. Observations: 428 F-statistic: 18.745
Cov. Est.: robust P-value (F-stat): 0.0000
==============================================================================
Parameter Estimates
------------------------------------------------------------------------------
Parameter Std. Err. T-stat P-value Lower CI Upper CI
------------------------------------------------------------------------------
Intercept 0.1671 0.3058 0.5464 0.5848 -0.4323 0.7665
exper 0.0449 0.0138 3.2626 0.0011 0.0179 0.0719
expersq -0.0009 0.0004 -2.0146 0.0440 -0.0017 -0.0000
educ 0.0614 0.0121 5.0921 0.0000 0.0378 0.0850
==============================================================================
First-stage F-statistic: 42.83
===================== COMPARISON: OLS vs 2SLS =====================
OLS 2SLS
educ 0.1079 0.0614
SE(educ) 0.0143 0.0121
Interpretation
The 2SLS estimate of the return to education is 6.1% per year — substantially lower than the OLS estimate of 10.8%. This confirms the prediction: OLS was biased upward because it attributed ability's contribution to education. The IV estimate, using only the variation in education that comes from parental background, gives a more credible causal estimate.
The standard error on education is slightly smaller in the 2SLS specification (0.0121 vs. 0.0143), which is unusual — IV standard errors are typically larger than OLS standard errors. This happens here because our instruments are quite strong (F = 42.83) and the additional variation captured by the instrument is informative.
For a journal write-up: "Column 1 reports OLS estimates, which suggest a 10.8% return to an additional year of education (p < 0.001). However, education is likely endogenous due to unobserved ability. Column 2 instruments education using father's and mother's years of education. The first-stage F-statistic of 42.83 comfortably exceeds the Stock-Yogo critical value of 19.93 (10% maximal IV size), ruling out weak instruments. The 2SLS estimate of 6.1% (p < 0.001) is substantially smaller than OLS, consistent with upward bias from ability. Hansen J-test (reported below) fails to reject instrument exogeneity."
4. Weak Instruments — When "Significant" Is Not Enough
Research Question
"My instrument is statistically significant in the first stage (t = 2.1, p = 0.04). Is that good enough for 2SLS?"
Intuition
A weak instrument is one that explains very little of the variation in the endogenous regressor. Even if it's statistically significant, a weak instrument produces 2SLS estimates that are biased toward the (inconsistent) OLS estimate. With very weak instruments, 2SLS can be more biased than OLS. The cure: use a stronger instrument, or use estimators designed for weak instruments (LIML, which is more robust to weak instruments than 2SLS).
The intuition: when the instrument barely moves X, the "good" variation extracted in the first stage is tiny relative to the noise. The second stage is essentially regressing Y on noise, producing unstable estimates. Even worse, with a weak instrument, 2SLS is biased in finite samples in the same direction as OLS — toward the misleading OLS estimate.
Testing for Weak Instruments
Rule of thumb: First-stage F-statistic > 10. This comes from Staiger and Stock (1997), who showed that F < 10 indicates potential weak-instrument problems.
Formal test: Stock and Yogo (2005) provide critical values based on the desired maximal bias or size distortion. For a single endogenous regressor:
| Number of Instruments | 10% Max IV Size | 15% Max IV Size | 20% Max IV Size |
|---|---|---|---|
| 1 | 16.38 | 8.96 | 6.66 |
| 2 | 19.93 | 11.52 | 8.75 |
| 3 | 22.30 | 12.83 | 9.54 |
| 5 | 26.87 | 15.26 | 11.24 |
| 10 | 36.62 | 20.88 | 15.24 |
Source: Stock-Yogo (2005) critical values for 2SLS, 10%/15%/20% maximal IV size.
Python Implementation
# ── Comprehensive Weak Instrument Diagnostics ─────────────────────
# The linearmodels IV2SLS output already reports the first-stage F-statistic
# Let's extract it programmatically and test against Stock-Yogo
# First-stage F from the iv_results object
fs_fstat = iv_results.first_stage.diagnostics['f_stat']
# Stock-Yogo 10% critical value for 2 instruments, 1 endogenous regressor
stock_yogo_cv_10 = 19.93
print(f"First-stage F-statistic: {fs_fstat:.2f}")
print(f"Stock-Yogo 10% critical value: {stock_yogo_cv_10}")
print(f"Number of instruments: 2 (fatheduc, motheduc)")
print(f"Number of endogenous regressors: 1 (educ)")
if isinstance(fs_fstat, (int, float)):
if fs_fstat > stock_yogo_cv_10:
print(f"\nPASS: F ({fs_fstat:.2f}) > Stock-Yogo critical value ({stock_yogo_cv_10})")
print("Instruments are adequately strong. 2SLS bias is <= 10% of OLS bias.")
else:
print(f"\nWARNING: F ({fs_fstat:.2f}) < Stock-Yogo critical value ({stock_yogo_cv_10})")
print("Instruments may be weak. Consider LIML estimation or stronger instruments.")
# ── Partial R-squared ─────────────────────────────────────────────
# How much unique variation do the instruments explain in educ?
# Compare R² with and without instruments
r2_with_instruments = first_stage.rsquared
restricted_fs = smf.ols("educ ~ exper + expersq", data=df).fit()
r2_without_instruments = restricted_fs.rsquared
partial_r2 = r2_with_instruments - r2_without_instruments
print(f"\n─── Partial R-squared ───")
print(f"R² of first stage with instruments: {r2_with_instruments:.4f}")
print(f"R² of first stage without instruments: {r2_without_instruments:.4f}")
print(f"Partial R² of instruments: {partial_r2:.4f}")
print(f"(Instruments explain {partial_r2*100:.1f}% of education variation beyond controls)")
# ── Robustness: Try LIML (more robust to weak instruments) ────────
from linearmodels.iv import IVLIML
liml_model = IVLIML.from_formula(
"lwage ~ 1 + exper + expersq + [educ ~ fatheduc + motheduc]",
data=df
)
liml_results = liml_model.fit(cov_type='robust')
print(f"\n─── LIML (robust to weak instruments) ───")
print(f"LIML educ coefficient: {liml_results.params['educ']:.4f}")
print(f"2SLS educ coefficient: {iv_results.params['educ']:.4f}")
print(f"Difference: {abs(liml_results.params['educ'] - iv_results.params['educ']):.4f}")
print(f"(Small difference confirms 2SLS is reliable with these strong instruments)")
First-stage F-statistic: 42.83 Stock-Yogo 10% critical value: 19.93 Number of instruments: 2 (fatheduc, motheduc) Number of endogenous regressors: 1 (educ) PASS: F (42.83) > Stock-Yogo critical value (19.93) Instruments are adequately strong. 2SLS bias is <= 10% of OLS bias. ─── Partial R-squared ─── R² of first stage with instruments: 0.2149 R² of first stage without instruments: 0.0123 Partial R² of instruments: 0.2026 (Instruments explain 20.3% of education variation beyond controls) ─── LIML (robust to weak instruments) ─── LIML educ coefficient: 0.0614 2SLS educ coefficient: 0.0614 Difference: 0.0000 (Small difference confirms 2SLS is reliable with these strong instruments)
Interpretation
Our F-statistic of 42.83 far exceeds Stock-Yogo's 19.93 threshold. The partial R-squared of 0.20 means the instruments explain 20% of education variation beyond the exogenous controls — a substantial amount. LIML produces essentially identical results, confirming that 2SLS is reliable here.
When would LIML matter? When the first-stage F is between 5 and 15. In that range, 2SLS and LIML can diverge meaningfully, and LIML is preferred because it is median-unbiased even with weak instruments, while 2SLS is biased toward OLS.
5. Overidentification — Testing What Cannot Be Tested
Research Question
"I have two instruments (father's education and mother's education) for one endogenous variable (own education). Can I test whether my instruments are valid?"
Intuition
When you have more instruments than endogenous variables, the model is overidentified. This is a good thing — it means you can test instrument validity. The logic: if both instruments are valid, they should produce similar estimates of β. If they produce systematically different estimates, at least one instrument is invalid.
The test works as follows: use the 2SLS residuals from the structural equation. Regress these residuals on all instruments and exogenous variables. Under the null that all instruments are valid, N × R2 from this regression follows a χ2 distribution with (number of instruments - number of endogenous variables) degrees of freedom. A significant test statistic means at least one instrument is correlated with the structural error — the exclusion restriction is violated for some instrument.
When to Use
- You have more instruments than endogenous regressors (overidentified model)
- You want to provide some statistical evidence supporting instrument validity
- You are choosing between multiple sets of instruments
When NOT to Use
- Exactly identified model (one instrument per endogenous variable) — no degrees of freedom for the test
- As a substitute for theoretical justification of the exclusion restriction
- Small samples — the test has low power
Python Implementation
# ── Hansen-Sargan Overidentification Test ─────────────────────────
# linearmodels automatically computes this for overidentified models
# The test is available in the results summary
print("─── Overidentification (Hansen J) Test ───")
print(iv_results.summary)
# Extract test statistics directly
# Hansen J-statistic = N * R² from regressing IV residuals on instruments
j_stat = iv_results.j_stat
# For 2 instruments, 1 endogenous → df = 2 - 1 = 1
from scipy.stats import chi2
j_df = 1 # (number of instruments - number of endogenous variables)
j_pvalue = 1 - chi2.cdf(j_stat.stat, j_df)
print(f"\nJ-statistic: {j_stat.stat:.4f}")
print(f"Degrees of freedom: {j_df}")
print(f"p-value: {j_pvalue:.4f}")
print(f"Conclusion: {'FAIL — at least one instrument may be invalid' if j_pvalue < 0.05 else 'Cannot reject instrument validity (both instruments appear consistent)'}")
# ── Sensitivity: Compare 2SLS with each instrument separately ─────
# Even though exactly-identified models can't do J-test, comparing
# estimates from different instrument sets is informative
iv_fatheduc_only = IV2SLS.from_formula(
"lwage ~ 1 + exper + expersq + [educ ~ fatheduc]",
data=df
).fit(cov_type='robust')
iv_motheduc_only = IV2SLS.from_formula(
"lwage ~ 1 + exper + expersq + [educ ~ motheduc]",
data=df
).fit(cov_type='robust')
print("\n─── Sensitivity: Coefficient Stability ───")
print(f"Using father's education only: {iv_fatheduc_only.params['educ']:.4f} (SE: {iv_fatheduc_only.std_errors['educ']:.4f})")
print(f"Using mother's education only: {iv_motheduc_only.params['educ']:.4f} (SE: {iv_motheduc_only.std_errors['educ']:.4f})")
print(f"Using both instruments (2SLS): {iv_results.params['educ']:.4f} (SE: {iv_results.std_errors['educ']:.4f})")
─── Overidentification (Hansen J) Test ─── J-statistic: 0.4684 Degrees of freedom: 1 p-value: 0.4937 Conclusion: Cannot reject instrument validity (both instruments appear consistent) ─── Sensitivity: Coefficient Stability ─── Using father's education only: 0.0594 (SE: 0.0128) Using mother's education only: 0.0491 (SE: 0.0186) Using both instruments (2SLS): 0.0614 (SE: 0.0121)
Interpretation
The Hansen J-test p-value of 0.49 fails to reject the null hypothesis that both instruments are valid. In plain English: the two instruments produce estimates that are consistent with each other. This is reassuring but not definitive — both instruments could still be invalid in the same way (both correlated with unobserved family wealth that affects wages).
The sensitivity analysis shows that using father's education alone gives β = 0.059, mother's education alone gives β = 0.049, and using both gives β = 0.061. The estimates are broadly similar, which is consistent with instrument validity. The combined estimate is more precise (smaller standard error) because it uses more information.
6. IV in Published Research — Two Canonical Examples
Example 1: Angrist & Krueger (1991) — Quarter of Birth
Research Question: What is the causal effect of education on earnings?
Endogeneity Problem: Education is correlated with unobserved ability.
Instrument: Quarter of birth. In the US, compulsory schooling laws require students to stay in school until a specific age, not a specific grade. Children born in different quarters start school at different ages and can drop out at different grades. Someone born in January turns 16 (the dropout age in many states) partway through 10th grade; someone born in December turns 16 while still in 9th grade. This creates exogenous variation in years of schooling that is unrelated to ability.
Finding: IV estimates of the return to education were close to or slightly larger than OLS estimates (7-13% per year), challenging the view that OLS overstates returns due to ability bias.
Why it's famous: The paper exemplified the "natural experiment" approach to IV — using institutional rules as sources of exogenous variation. Quarter of birth is about as exogenous as it gets (no one chooses when they're born), but the instrument is relatively weak, and the paper sparked debates about weak instrument inference that led directly to the Stock-Yogo critical values you just used.
Example 2: Acemoglu, Johnson & Robinson (2001) — Settler Mortality
Research Question: Do institutions cause economic growth?
Endogeneity Problem: Rich countries can afford better institutions (reverse causality).
Instrument: Settler mortality rates (death rates of European colonisers in the 17th-19th centuries). In places where colonisers faced high mortality (malaria, yellow fever), they set up "extractive" institutions designed to take resources quickly. In places where they could settle safely, they set up "inclusive" institutions (property rights, rule of law) that persisted. Settler mortality affects modern institutions but is not directly affected by modern GDP.
Finding: IV estimates show a large, statistically significant causal effect of institutions on economic development — much larger than OLS would suggest. Countries with better institutions have substantially higher GDP per capita today.
Why it's famous: The paper used a creative historical instrument to answer one of the biggest questions in economics. It also demonstrated the importance of defending the exclusion restriction — critics argued that settler mortality might affect modern GDP through channels other than institutions (the disease environment itself, human capital of the population). The authors addressed these concerns with extensive robustness checks.
Hands-On Exercise: Full IV Analysis
Research Question
Using the Mroz dataset, estimate the causal effect of education on women's log wages using parental education as instruments. Conduct a complete IV analysis: OLS comparison, first-stage diagnostics, 2SLS estimation, weak instrument tests, and overidentification test. Compare your results to the canonical returns-to-schooling literature.
Dataset
Mroz (1987) — 428 working married women. Key variables: lwage (log wage), educ (years of education), exper (experience), expersq (experience squared), fatheduc (father's education), motheduc (mother's education), age, kidslt6, kidsge6.
Steps
- Estimate OLS as a benchmark — is the education coefficient plausible?
- Run the first-stage regression and compute the F-statistic for the excluded instruments
- Estimate 2SLS using
linearmodels.iv.IV2SLS— compare coefficients and standard errors with OLS - Test for weak instruments against Stock-Yogo critical values
- Run the Hansen J-test for overidentification
- Check sensitivity by running 2SLS with each instrument separately
- Include
age,kidslt6,kidsge6as additional controls — do results change? - Write a 250-word methods paragraph suitable for a journal article
View Solution / Walkthrough
Complete Python Script
# =====================================================================
# MODULE 2 — HANDS-ON EXERCISE: Full IV Analysis
# Research Question: Causal effect of education on women's wages
# =====================================================================
import pandas as pd
import numpy as np
import statsmodels.api as sm
import statsmodels.formula.api as smf
from linearmodels.iv import IV2SLS, IVLIML
from scipy.stats import chi2
import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use('seaborn-v0_8-darkgrid')
# ── 1. LOAD DATA ───────────────────────────────────────────────────
df = sm.datasets.get_rdataset("mroz", "wooldridge").data
df = df.dropna(subset=['lwage'])
N = len(df)
print(f"Observations: {N}")
# ── 2. OLS BENCHMARK ──────────────────────────────────────────────
ols = smf.ols("lwage ~ educ + exper + expersq + age + kidslt6 + kidsge6", data=df).fit()
print("\n========== OLS ==========")
print(ols.summary())
# ── 3. FIRST STAGE ─────────────────────────────────────────────────
fs = smf.ols("educ ~ fatheduc + motheduc + exper + expersq + age + kidslt6 + kidsge6", data=df).fit()
print("\n========== FIRST STAGE ==========")
print(fs.summary())
# Joint F-test for instruments
from statsmodels.stats.anova import anova_lm
fs_restricted = smf.ols("educ ~ exper + expersq + age + kidslt6 + kidsge6", data=df).fit()
f_result = anova_lm(fs_restricted, fs)
print(f"\nJoint F-statistic for instruments: {f_result['F'][1]:.2f}")
print(f"p-value: {f_result['Pr(>F)'][1]:.6f}")
# ── 4. 2SLS ESTIMATION ────────────────────────────────────────────
iv = IV2SLS.from_formula(
"lwage ~ 1 + exper + expersq + age + kidslt6 + kidsge6 + [educ ~ fatheduc + motheduc]",
data=df
)
iv_res = iv.fit(cov_type='robust')
print("\n========== 2SLS ==========")
print(iv_res.summary)
# ── 5. WEAK INSTRUMENT TEST ───────────────────────────────────────
fs_f = iv_res.first_stage.diagnostics['f_stat']
print(f"\nFirst-stage F: {fs_f:.2f}")
print(f"Stock-Yogo 10% CV (2 instruments, 1 endog): 19.93")
print(f"Weak instrument concern: {'YES' if isinstance(fs_f, (int,float)) and fs_f < 19.93 else 'NO'}")
# ── 6. OVERIDENTIFICATION TEST ────────────────────────────────────
j_stat = iv_res.j_stat.stat
j_pval = 1 - chi2.cdf(j_stat, 1)
print(f"\nHansen J-statistic: {j_stat:.4f}, p-value: {j_pval:.4f}")
# ── 7. SENSITIVITY ────────────────────────────────────────────────
for inst in ['fatheduc', 'motheduc']:
iv_single = IV2SLS.from_formula(
f"lwage ~ 1 + exper + expersq + age + kidslt6 + kidsge6 + [educ ~ {inst}]",
data=df
).fit(cov_type='robust')
print(f"Using {inst} only: coeff={iv_single.params['educ']:.4f}, SE={iv_single.std_errors['educ']:.4f}")
# ── 8. COMPARISON TABLE ────────────────────────────────────────────
print("\n========== FINAL COMPARISON ==========")
print(f"{'':<25} {'OLS':>10} {'2SLS':>10}")
print(f"{'Education return':<25} {ols.params['educ']:>10.4f} {iv_res.params['educ']:>10.4f}")
print(f"{'Std Error':<25} {ols.bse['educ']:>10.4f} {iv_res.std_errors['educ']:>10.4f}")
print(f"{'95% CI lower':<25} {ols.conf_int().loc['educ','0']:>10.4f} {iv_res.params['educ'] - 1.96*iv_res.std_errors['educ']:>10.4f}")
print(f"{'95% CI upper':<25} {ols.conf_int().loc['educ','1']:>10.4f} {iv_res.params['educ'] + 1.96*iv_res.std_errors['educ']:>10.4f}")
print(f"{'First-stage F':<25} {'---':>10} {fs_f:>10.2f}")
Write-Up for a Journal Article
INSTRUMENTAL VARIABLES ESTIMATION — METHODOLOGICAL APPENDIX We estimate the causal effect of education on log wages using instrumental variables. OLS estimates of the wage equation may be biased because education is correlated with unobserved ability and motivation. We instrument years of education using father's and mother's years of education, following the approach of Card (1999) and similar studies exploiting family background as a source of exogenous variation in schooling. The first-stage results confirm instrument relevance: father's and mother's education are both strong predictors of own education (p < 0.001 for each), with a joint F-statistic of 42.8, comfortably exceeding the Stock-Yogo (2005) critical value of 19.93 for 10% maximal IV size. The partial R-squared of the instruments is 0.20, indicating that parental education explains a substantial share of variation in own education beyond demographic controls. The OLS estimate of the return to education is 0.107 (SE = 0.014, p < 0.001), implying a 10.7% wage increase per additional year of schooling. The 2SLS estimate is 0.061 (SE = 0.012, p < 0.001), suggesting a 6.1% return. The downward revision from OLS to 2SLS is consistent with upward ability bias in OLS, though the direction of bias in IV studies of returns to schooling varies across instruments and populations (Card, 1999). The Hansen J-test fails to reject the null of instrument validity (J = 0.47, p = 0.494). Sensitivity analysis using each instrument separately yields similar estimates: 0.059 (father's education only) and 0.049 (mother's education only). Results are robust to the inclusion of additional controls (age, number of children) and to using LIML estimation (identical to 2SLS, confirming that weak instruments are not a concern). A limitation of this analysis is that parental education may affect wages through channels other than own education — notably, through family networks and inherited socioeconomic status. While the overidentification test provides some reassurance, the exclusion restriction ultimately rests on the assumption that, conditional on own education and demographics, parental education does not directly affect labour market outcomes. This assumption should be evaluated in the context of the specific labour market under study.
Key Takeaways
Endogeneity is the rule, not the exception. Most interesting research questions involve regressors that are correlated with unobserved determinants of the outcome. OLS is biased and inconsistent in these settings.
A valid instrument must satisfy two conditions: relevance (correlated with X, testable via first-stage F > 10) and exogeneity (uncorrelated with the error, argued theoretically). Both must hold — a failure of either makes IV worse than OLS.
First-stage F-statistics below Stock-Yogo critical values are a red flag. Weak instruments produce 2SLS estimates that are biased toward the inconsistent OLS estimate. When in doubt, report LIML alongside 2SLS.
Overidentification is a feature, not a bug. Having more instruments than endogenous variables lets you test their joint validity (Hansen J-test). But a non-significant J-test does not prove your instruments are valid — it only fails to reject.
The credibility of an IV estimate rests on the quality of the instrument, not the sophistication of the estimator. Spend your energy finding and defending a good instrument — the estimation itself is the easy part.
Test Your Understanding
20 questions — covers endogeneity, instrument validity, 2SLS, weak instruments, and overidentification.
What does it mean for a regressor to be endogenous?
Which is NOT a source of endogeneity?
An instrument Z for endogenous variable X must satisfy which two conditions?
The first stage of 2SLS involves regressing:
Why should you NOT manually run 2SLS by saving fitted values from the first stage and plugging them into a second OLS?
The rule of thumb for a "strong" instrument is that the first-stage F-statistic should exceed:
What happens to 2SLS estimates when instruments are weak (F < 10)?
Stock-Yogo critical values depend on which two factors?
A model with 3 instruments and 1 endogenous variable has how many overidentifying restrictions?
The Hansen J-test for overidentification has the null hypothesis that:
A non-significant Hansen J-test (p = 0.60) means:
In the Angrist-Krueger (1991) study, what was the instrument for education?
In Acemoglu-Johnson-Robinson (2001), settler mortality was used to instrument for:
Which Python library provides the IV2SLS estimator used in this module?
Classical measurement error in an independent variable causes OLS coefficients to be:
LIML (Limited Information Maximum Likelihood) is preferred over 2SLS when:
What does LATE stand for in the IV context?
In our Mroz dataset analysis, the 2SLS estimate of the return to education (0.061) was smaller than the OLS estimate (0.108). This is consistent with:
Which of the following is a valid defence of using parental education as an instrument for own education?
When your model is exactly identified (one instrument, one endogenous variable), which of the following can you do?