An experimental perspective on the instrumental variable
Chapter 21 treats IV as an experimental design problem: assignment \(Z\) shifts treatment uptake \(D\), and the Wald ratio turns those two reduced-form contrasts into a complier-effect estimate.
Show code
from pathlib import Pathimport matplotlib.pyplot as pltimport numpy as npimport pandas as pdimport crabbymetrics as cmnp.set_printoptions(precision=4, suppress=True)def repo_root():for candidate in [Path.cwd().resolve(), *Path.cwd().resolve().parents]:if (candidate /"ding_w_source").exists():return candidateraiseFileNotFoundError("could not locate ding_w_source from the current working directory")def simulate_experiment(rng, shares, n=300): complier, always, never = shares n_c =int(round(n * complier)) n_a =int(round(n * always)) n_n = n - n_c - n_a d0 = np.r_[np.zeros(n_c), np.ones(n_a), np.zeros(n_n)] d1 = np.r_[np.ones(n_c), np.ones(n_a), np.zeros(n_n)] y0 = np.r_[ rng.normal(1.0, 1.0, n_c), rng.normal(0.0, 1.0, n_a), rng.normal(2.0, 1.0, n_n), ] y1 = y0.copy() y1[:n_c] = rng.normal(3.0, 1.0, n_c) z = rng.binomial(1, 0.5, n).astype(float) d = z * d1 + (1.0- z) * d0 y = d * y1 + (1.0- d) * y0return z, d, ydef wald(z, d, y): rf_d = d[z ==1.0].mean() - d[z ==0.0].mean() rf_y = y[z ==1.0].mean() - y[z ==0.0].mean()return rf_y / rf_ddef wald_delta_se(z, d, y): beta = wald(z, d, y) adj = y - beta * d v_adj = adj[z ==1.0].var(ddof=1) / np.sum(z ==1.0) + adj[z ==0.0].var(ddof=1) / np.sum(z ==0.0) rf_d = d[z ==1.0].mean() - d[z ==0.0].mean()return np.sqrt(v_adj) /abs(rf_d)def wald_bootstrap_se(z, d, y, rng, n_boot=40): n =len(z) draws = np.zeros(n_boot)for b inrange(n_boot): idx = rng.choice(n, size=n, replace=True) draws[b] = wald(z[idx], d[idx], y[idx])return draws.std(ddof=1)
Strong IV mean Wald = 1.9865, empirical sd = 0.4097, mean delta se = 0.4183, mean bootstrap se = 0.4393
Weak IV mean Wald = 1.9794, empirical sd = 1.1323, mean delta se = 1.3096, mean bootstrap se = 4.3935
Very weak IV mean Wald = 1.4279, empirical sd = 11.7076, mean delta se = 18.0295, mean bootstrap se = nan
The R script closes with the JOBS data from the mediation package. Assignment to the job-search intervention is the instrument, actual compliance is the treatment uptake, and job-search self-efficacy is the outcome. Because the design has one-sided noncompliance, the Wald estimand is the complier effect of uptake among those induced to comply by assignment.