Taller 4: Variables Instrumentales I

Carlos Daboin Contreras (cdaboincontreras@udesa.edu.ar)

2023-10-01

Resumen de contenido

Nuestra meta

Semana 1

  • Repasar la intuición detrás del método IV.

  • Analizaremos unos datos sintéticos.

Semana 2

  • Familiarizarnos con otros diseños y aplicaciones de IV.

  • Precauciones a la hora de usar IV.

Conceptos

  • Exogeneidad.

  • Experimentos naturales.

  • Relevancia del instrumento.

  • Instrumentos débiles.

  • Validez del instrumento.

  • “Good instruments feel weird”

Herramientas

  • AER::ivreg Función para producir estimados de IV de la libería AER.

  • modelsummary: Librería para presentar resultados de regresión.

  • haven: Librería para leer archivos .dta (Stata).

  • GGally: Librería muy útil para una inspección visual de estadísticas descriptivas.

Librerías

Usaremos las siguientes librerías:

library(haven)     # para abrir bases de datos en formato .dta
library(modelsummary)# para tablas

library(tidyverse) # libreria muy usada para manipular los datos y hacer grficos

library(broom)     # revisar output de modelos
library(AER)       # para usar el comando de variables instrumentales
library(gt)        # para hacer tablas
library(GGally)    # para hacer matriz de correlación

Motivando IV

Cuándo no podemos controlar toda la variabilidad endógena entre Y y X, podemos tratar de extraer la variación exógena de X.

Controlar: Remuevo lo que estorba

Remover lo explicado por otras variables añadiéndolas cómo control (o con experimento infalible.)

Instrumentar: Aislo lo que puedo

Uso otra(s) variable(s) para aislar lo que pueda de la variabilidad que me interesa estudiar.

Un ejemplo sintético

Creamos una base de datos en la que:

  • \(Cor(Y_iX_i)\neq0\)

  • \(Cor(X_iU_i)\neq0\)

  • \(Cor(X_iZ_i)\neq 0\)

  • \(Cor(Z_iU_i)= 0\)

df <- tibble(
  U = rnorm(5000),                # U es la variabilidad no observable
  Z = rbinom(5000, 1, .5),        # Z variable binaria que afecta solo a X
  X = 3 * U + 4 * Z + rnorm(5000),# X depende de U y Z
  Y = 5 * X + 7 * U + rnorm(5000))# Y depende de X y U
# A tibble: 6 × 4
       U     Z      X      Y
   <dbl> <int>  <dbl>  <dbl>
1  0.571     1  6.17   35.2 
2  1.11      1  7.82   46.6 
3  1.11      0  3.05   22.7 
4 -0.801     0 -0.405  -7.29
5 -1.23      0 -2.77  -22.0 
6  1.38      0  5.62   36.4 

Un ejemplo sintético

Creamos una base de datos en la que:

  • \(Cor(Y_iX_i)\neq0\)

  • \(Cor(X_iU_i)\neq0\)

  • \(Cor(X_iZ_i)\neq 0\)

  • \(Cor(Z_iU_i)= 0\)

df <- tibble(
  U = rnorm(5000),                
  Z = rbinom(5000, 1, .5),        
  X = 3 * U + 4 * Z + rnorm(5000),
  Y = 5 * X + 7 * U + rnorm(5000))

corr_1<- 
  GGally::ggpairs(data = df,
                  columns = c("Y", "X", "U")
  )

Un ejemplo sintético

Creamos una base de datos en la que:

  • \(Cor(Y_iX_i)\neq0\)

  • \(Cor(X_iU_i)\neq0\)

  • \(Cor(X_iZ_i)\neq 0\)

  • \(Cor(Z_iU_i)= 0\)

df <- tibble(
  U = rnorm(5000),                
  Z = rbinom(5000, 1, .5),        
  X = 3 * U + 4 * Z + rnorm(5000),
  Y = 5 * X + 7 * U + rnorm(5000))

# Modelo simple se equivoca
ols1<- lm(Y ~ X, df)

Call:
lm(formula = Y ~ X, data = df)

Residuals:
   Min     1Q Median     3Q    Max 
-13.38  -3.04   0.01   3.18  13.56 

Coefficients:
            Estimate Std. Error t value            Pr(>|t|)    
(Intercept)  -3.0033     0.0690   -43.5 <0.0000000000000002 ***
X             6.4943     0.0162   402.0 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 4.27 on 4998 degrees of freedom
Multiple R-squared:  0.97,  Adjusted R-squared:  0.97 
F-statistic: 1.62e+05 on 1 and 4998 DF,  p-value: <0.0000000000000002

\(\hat\beta_1\) Está sesgado! Sabemos que el efecto es 5.

Un ejemplo sintético

Creamos una base de datos en la que:

  • \(Cor(Y_iX_i)\neq0\)

  • \(Cor(X_iU_i)\neq0\)

  • \(Cor(X_iZ_i)\neq 0\)

  • \(Cor(Z_iU_i)= 0\)

df <- tibble(
  U = rnorm(5000),                
  Z = rbinom(5000, 1, .5),        
  X = 3 * U + 4 * Z + rnorm(5000),
  Y = 5 * X + 7 * U + rnorm(5000))

corr_2<- ggpairs(data = mutate(df,Z = as.logical(Z)),
                  columns = c("Y", "X", "U", "Z"))

Usemos \(Z_i\) para aislar la variación exógena de \(X_i\)

Instrumentando por \(Z_i\)

Aprovechemos que \(Cor(X_i,Z_i)\neq0\) (relevancia) y que \(Cor(U_iZ_i)=0\) (validez) para extraer la variabilidad exógena de \(X_i\) (\(\hat X_i^z\)) y buscar \(\hat\beta_1\).

Primera etapa etapa:

\[ X_i=\alpha_0 + \alpha_1 Z_i+\psi_i \]

\[ \hat X_i^z=\hat\alpha_0 + \hat\alpha_1 Z_i \]

Segunda etapa:

\[ Y_i=\beta_0 + \beta_1 \hat X_i^z+\mu_i \]

Instrumentando por \(Z_i\)

Primera etapa etapa:

\[ X_i=\alpha_0 + \alpha_1 Z_i+\psi_i \]

\[ \hat X_i^z=\hat\alpha_0 + \hat\alpha_1 Z_i \]

Segunda etapa:

\[ Y_i=\beta_0 + \beta_1 \hat X_i^z+\mu_i \]

# Primera forma
# IV1 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

df$X_hat <- df$X - FS$residuals  # Diganme que es esto

# IV1 Paso 2: Regresión de valores predichos (Segunda etapa)
IV1 <- lm(Y ~ X_hat, df)

broom::tidy(IV1)
# A tibble: 2 × 5
  term        estimate std.error statistic   p.value
  <chr>          <dbl>     <dbl>     <dbl>     <dbl>
1 (Intercept)    0.152     0.454     0.335 7.38e-  1
2 X_hat          4.95      0.163    30.3   1.86e-185

Otras formas de hallar IV \(\beta_1\)

Primera etapa etapa:

\[ X_i=\alpha_0 + \alpha_1 Z+\psi_i \]

\[ \hat X_i^z=\hat\alpha_0 + \hat\alpha_1 Z \]

Segunda etapa:

\[ Y_i=\beta_0 + \beta_1 \hat X_i^z+\mu_i \]

# IV1 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

df$X_hat <- df$X - FS$residuals  # Diganme que es esto

# IV1 Paso 2: Regresión de Y con X predichos (Segunda etapa)
IV1 <- lm(Y ~ X_hat, df)

broom::tidy(IV1)
# A tibble: 2 × 5
  term        estimate std.error statistic   p.value
  <chr>          <dbl>     <dbl>     <dbl>     <dbl>
1 (Intercept)    0.152     0.454     0.335 7.38e-  1
2 X_hat          4.95      0.163    30.3   1.86e-185

Primera etapa:

\[ X_i=\alpha_0 + \alpha_1 Z+\psi_i \]

\[ \hat X_i^z=\hat\alpha_0 + \hat\alpha_1 Z \] Reduced form:

\[ Y_i=\gamma_0 + \gamma_1 Z+\nu_i \]

\[ \hat Y_i^z=\hat\gamma_0 + \hat\gamma_1 Z \]

Segunda etapa:

\[ \hat Y_i^z=\beta_0 + \beta_1 \hat X_i^z+\mu_i \]

# IV2 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

df$X_hat <- df$X - FS$residuals  # Diganme que es esto

# IV Paso 2: Efecto de Z sobre Y 
RF <- lm(Y ~ Z, df)

df$Y_hat <- df$Y - RF$residuals 

# IV2 Paso 3: Regresión de valores predichos (Segunda etapa)
IV2 <- lm(Y_hat ~ X_hat, df)

broom::tidy(IV2)
# A tibble: 2 × 5
  term        estimate std.error statistic p.value
  <chr>          <dbl>     <dbl>     <dbl>   <dbl>
1 (Intercept)    0.152  2.09e-14   7.26e12       0
2 X_hat          4.95   7.54e-15   6.57e14       0

Sólo válida para instrumentos binarios.

Primera etapa:

\[ X_i=\alpha_0 + \alpha_1 Z+\psi_i \] Reduced form:

\[ Y_i=\gamma_0 + \gamma_1 Z+\nu_i \]

Segunda etapa:

\[ \beta_1=\frac{\gamma_1}{\alpha_1} \]

# IV3 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

(fs_coef <- FS$coefficients[2])
    Z 
3.895 
# IV3 Paso 2: Efecto de Z spbre Y 
RF <- lm(Y ~ Z, df)
(rf_coef <- RF$coefficients[2])
    Z 
19.29 
# IV3 Paso 3: Fracción de coeficientes
IV <-  rf_coef / fs_coef

IV
    Z 
4.953 

Igual que en los anteriores, sólo que esta vez está resumido.

# IV en un solo paso:
IV4 <- ivreg(Y ~ X |  Z, data=df)

summary(IV4)

Call:
ivreg(formula = Y ~ X | Z, data = df)

Residuals:
      Min        1Q    Median        3Q       Max 
-28.86414  -4.78542  -0.00787   4.78833  27.30088 

Coefficients:
            Estimate Std. Error t value            Pr(>|t|)    
(Intercept)   0.1520     0.1449    1.05                0.29    
X             4.9530     0.0522   94.97 <0.0000000000000002 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Residual standard error: 7.18 on 4998 degrees of freedom
Multiple R-Squared: 0.914,  Adjusted R-squared: 0.914 
Wald test: 9.02e+03 on 1 and 4998 DF,  p-value: <0.0000000000000002 

Tienen varias opciones

Hay varias librerías para hacer 2SLS en un solo paso. Cada una tiene sus pros y contras, y también su propia sintaxis.

AER::ivreg(outcome ~ treatment | instrument) Includes special tests for weak instruments.
estimatr::iv_robust(outcome ~ treatment | instrument) Handles robust and clustered standard errors
ivreg::ivreg(outcome ~ treatment | instrument) Includes a ton of fancy diagnostics
felm::lfe(outcome ~ treatment | fixed effects | instrument) Benefits: Handles fixed effects really quickly
plm::plm(outcome ~ treatment | instrument) Benefits: Handles panel data (country/year, state/year, etc.)

Código listo para llevar a casa

#1. librerias
library(haven)     # para abrir bases de datos en formato .dta
library(modelsummary)# para tablas
library(tidyverse) # libreria muy usada para manipular los datos y hacer grficos
library(broom)     # revisar output de modelos
library(AER)       # para usar el comando de variables instrumentales
library(gt)        # para hacer tablas
library(GGally)    # para hacer matriz de correlación

#2. Datos sinteticos
df <- tibble(
  U = rnorm(5000),                # U es la variabilidad no observable
  Z = rbinom(5000, 1, .5),        # Z variable binaria que afecta solo a X
  X = 3 * U + 4 * Z + rnorm(5000),# X depende de U y Z
  Y = 5 * X + 7 * U + rnorm(5000))# Y depende de X y U

#3. Correlograma
corr_2<- GGally::ggpairs(data = df,columns = c("Y", "X", "U","Z"))

#4. classic OLS 
ols1<- lm(Y ~ X, df)# Modelo simple se equivoca
summary(ols1)

# 5.1 IV 
# Primera forma
# IV1 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

df$X_hat <- df$X - FS$residuals  # Diganme que es esto

# IV1 Paso 2: Regresión de valores predichos (Segunda etapa)
IV1 <- lm(Y ~ X_hat, df)

broom::tidy(IV1)

# IV2 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

df$X_hat <- df$X - FS$residuals  # Diganme que es esto

# IV Paso 2: Efecto de Z sobre Y 
RF <- lm(Y ~ Z, df)

df$Y_hat <- df$Y - RF$residuals 

# IV2 Paso 3: Regresión de valores predichos (Segunda etapa)
IV2 <- lm(Y_hat ~ X_hat, df)

broom::tidy(IV2)

# IV3 Paso 1: Efecto de Z sobre X (Primera etapa)
FS <- lm(X ~ Z, df)

(fs_coef <- FS$coefficients[2])

# IV3 Paso 2: Efecto de Z spbre Y 
RF <- lm(Y ~ Z, df)
(rf_coef <- RF$coefficients[2])

# IV3 Paso 3: Fracción de coeficientes
IV <-  rf_coef / fs_coef

IV

# IV en un solo paso:
IV4 <- ivreg(Y ~ X |  Z, data=df)

summary(IV4)

Fin