Causal Inference III(b) — Weak-Instrument-Robust Inference (R companion)¶

ivmodel (Anderson-Rubin, CLR) and ivDiag (tF, effective-F)¶

R has the reference implementations of weak-instrument-robust inference:

  • ivmodel (Kang, Jiang, Zhao & Small) — 2SLS plus the weak-IV-robust Anderson-Rubin and conditional likelihood ratio (CLR) confidence intervals in one object;
  • ivDiag (Lal, Lockwood, Xu, et al.) — the tF procedure of Lee-McCrary-Moon-Weidner, the effective first-stage F, and AR, packaged as the modern IV robustness suite.

We apply them to the Card returns-to-schooling data, reproducing the Python notebook: the naive 2SLS interval excludes zero, but the robust AR interval is wider (just excluding zero), and the tF interval — with its inflated critical value — includes zero. The estimate is borderline once weak-instrument uncertainty is taken seriously.

1. Anderson-Rubin and CLR — ivmodel¶

ivmodel() fits the model and exposes several inference methods at once. The Anderson-Rubin confidence interval (AR.test) is valid regardless of instrument strength; the CLR interval (Moreira) is the near-optimal weak-IV-robust interval. Both are wider than, and asymmetric relative to, the naive 2SLS interval — reflecting the F ≈ 13 first stage that the old "F > 10" rule wrongly treated as strong.

In [1]:
suppressMessages({library(ivmodel)})
d<-read.csv("card.csv")
ctrl<-c("exper","expersq","black","south","smsa","reg661","reg662","reg663","reg664","reg665","reg666","reg667","reg668","smsa66")
d<-d[complete.cases(d[,c("lwage","educ","nearc4",ctrl)]),]; X<-as.matrix(d[,ctrl])
iv<-ivmodel(Y=d$lwage, D=d$educ, Z=d$nearc4, X=X)
ar<-AR.test(iv)
tsls_est<-coef(iv)["TSLS","Estimate"]; tsls_se<-coef(iv)["TSLS","Std. Error"]
cat(sprintf("2SLS educ = %.4f (SE %.4f); Wald 95%% CI [%.4f, %.4f]\n", tsls_est, tsls_se, tsls_est-1.96*tsls_se, tsls_est+1.96*tsls_se))
cat(sprintf("Anderson-Rubin 95%% CI: [%.4f, %.4f]\n", ar$ci[1], ar$ci[2]))
clr<-CLR(iv); cat(sprintf("CLR 95%% CI: [%.4f, %.4f]\n", clr$ci[1,1], clr$ci[1,2]))
Warning message:
"package 'ivmodel' was built under R version 4.6.1"
2SLS educ = 0.1315 (SE 0.0550); Wald 95% CI [0.0238, 0.2392]
Anderson-Rubin 95% CI: [0.0248, 0.2848]
CLR 95% CI: [0.0248, 0.2848]

2. The tF procedure and effective-F — ivDiag¶

ivDiag computes the first-stage (effective) F, the tF interval with its F-dependent critical value $c_F$, and the AR interval, in one call. For Card the effective F is ~13–14, so $c_F\approx2.9$ (well above 1.96): the tF interval is much wider than the conventional one and includes zero. This is the Lee et al. recalibration in action — "F > 10" is far too lenient; valid conventional inference needs F > 104.7.

In [2]:
suppressMessages(library(ivDiag))
set.seed(1)
r<-ivDiag(data=d, Y="lwage", D="educ", Z="nearc4", controls=ctrl, cores=1, parallel=FALSE)
cat(sprintf("effective first-stage F = %.1f  (rule of thumb F>10 passes, but Lee et al. need F>104.7)\n", r$F_stat[["F.standard"]]))
tf<-r$tF
cat(sprintf("tF: adjusted critical value c_F = %.3f (vs naive 1.96)\n", tf[["cF"]]))
cat(sprintf("tF 95%% CI: [%.4f, %.4f]  %s\n", tf[["CI2.5%"]], tf[["CI97.5%"]], ifelse(tf[["CI2.5%"]]<=0 & tf[["CI97.5%"]]>=0,"(INCLUDES 0)","(excludes 0)")))
cat(sprintf("ivDiag AR 95%% CI: [%.4f, %.4f]\n", r$AR$ci[1], r$AR$ci[2]))
Warning message:
"package 'ivDiag' was built under R version 4.6.1"
Bootstrapping:


Bootstrap took18.290sec.


AR Test Inversion...


effective first-stage F = 13.3  (rule of thumb F>10 passes, but Lee et al. need F>104.7)
tF: adjusted critical value c_F = 2.934 (vs naive 1.96)
tF 95% CI: [-0.0273, 0.2904]  (INCLUDES 0)
ivDiag AR 95% CI: [0.0286, 0.2799]

3. All intervals side by side¶

Collecting the Card intervals: the conventional 2SLS Wald interval excludes zero; the robust Anderson-Rubin interval is wider and just excludes zero; the tF interval, with $c_F\approx2.9$, is wider still and includes zero. The neat significance of the naive interval was an artifact of treating F ≈ 13 as strong.

In [3]:
wald<-c(tsls_est-1.96*tsls_se, tsls_est+1.96*tsls_se)
arc<-c(ar$ci[1], ar$ci[2]); tfc<-c(tf[["CI2.5%"]], tf[["CI97.5%"]])
options(repr.plot.width=9, repr.plot.height=3.8)
plot(NA, xlim=c(-0.08,0.34), ylim=c(-0.5,2.7), yaxt="n", xlab="return to a year of schooling (log points)", ylab="",
     main="Card: conventional vs weak-IV-robust intervals")
cols<-c("#dd6b20","#2b6cb0","#6b46c1"); labs<-c("2SLS Wald","Anderson-Rubin","tF (Lee et al)")
cis<-list(wald,arc,tfc)
for(i in 1:3){ lines(cis[[i]], c(i-1,i-1), col=cols[i], lwd=5, lend=1); points(tsls_est, i-1, pch=19); text(cis[[i]][2]+0.005, i-1, labs[i], pos=4, cex=.85) }
abline(v=0, col="#c53030", lty=2); abline(v=tsls_est, col="grey", lty=3)
legend("topleft", c("no effect","2SLS point"), col=c("#c53030","grey"), lty=c(2,3), bty="n", cex=.8)
No description has been provided for this image

4. Summary¶

ivmodel and ivDiag reproduced the Python notebook's robust inference on Card: the Anderson-Rubin and CLR intervals (ivmodel) are wider than the conventional 2SLS interval and just exclude zero, while the tF interval (ivDiag), with its F-adjusted critical value $c_F\approx2.9$, includes zero. The effective F ≈ 13 clears the old "F > 10" rule but falls far short of the F > 104.7 that valid conventional inference actually requires — so the naive interval was too narrow and the estimate is genuinely borderline.

The workflow: after any IV analysis, report a weak-IV-robust interval — Anderson-Rubin or CLR (ivmodel) for general use, or tF (ivDiag) for a simple F-adjusted conventional interval — and never rely on the 2SLS Wald interval unless the first-stage F is very large. This completes the depth of the Instrumental Variables subsection, turning its weak-instrument diagnosis into valid inference.