AE12 Instrumental Variable

Author

Eduard (Eddie) Bukin

Published

September 23, 2026

Setup

library(tidyverse)
library(alr4)
library(GGally)
library(parameters)
library(performance)
library(see)
library(car)
library(broom)
library(modelsummary)
library(texreg)
library(correlation)
library(patchwork)
library(lmtest)
library(sandwich)
library(clubSandwich)
library(forcats)
library(modelbased)
library(emmeans)
library(ggeffects)
library(insight)
library(scales)
library(skimr)
library(glue)

ggplot2::theme_set(ggplot2::theme_bw())

knitr::opts_chunk$set(
  fig.align = "center",
  fig.width = 10,
  fig.asp = 0.618,
  fig.retina = 3,
  dpi = 300,
  out.width = "100%", 
  message = FALSE,
  echo = TRUE, 
  cache = FALSE
)

Goals:

  • learn how to fit the instrumental variable regression.

Exercise 1. Reproduce the effect schoolin on wage from the seminal paper:

Angrist, J. D., & Krueger, A. B. (1991). Does Compulsory School Attendance Affect Schooling and Earnings? The Quarterly Journal of Economics, 106, 979–1014. https://doi.org/10.2307/2937954

1 Data loading

Following variables are there:

lnw - log if wage

s - years of schooling

yob - year of birth

qob - quarter of birth

sob - week of birth

Load data, select and rename variable converting them to the factors if needed. Glimpse and do the summary statistics.

library(haven)
# dta <- 

1.2 Data visualisation

Make data for plotting.

Create a date variable and summaries everything by year and quarter of birth.

library(lubridate)
# plot_dta <-

Reproduce plots from the paper. Place right axis names and formatting.

# plot_dta %>%
#   ggplot() 
  

# plot_dta %>%
#   ggplot()

2 Produce an IV estimates using lm (only for the example)

Never use manual 2SLS estimations in real analysis as your SE are inefficient. This is an example for proving the point.

2.1 OLS

2.2 first stage with the 1th qurter only

2.2 first stage with all quarters of birth

2.3 second stages

2.4 compare the models

library(modelsummary)
# modelsummary(
#   list(
#   
#   ),
#   fmt = "%.3f",
#   estimate = "{estimate}{stars} ({std.error})",
#   statistic = NULL,
#   gof_map = c(
#     "adj.r.squared",
#     "nobs",
#     "statistic.Weak.instrument",
#     "statistic.Wu.Hausman",
#     "F",
#     "p.value"
#   ),
#   # coef_rename =
#   #   c(
#   #     "schooling" = "Years of schooling",
#   #     "schooling_hat" = "Years of schooling"
#   #   ),
#   # coef_omit = "yob|Intercept",
#   # stars = c("*" = 0.05, "**" = 0.01, "***" = 0.001),
#   title = "Manual 2SLS"
# )

3. Make an IV estimation

library(AER)

# # iv_q1 <- ivreg()
# summary(iv_q1, diagnostics = TRUE)
# 
# # iv_qall <- ivreg()
# summary(iv_qall, diagnostics = T)