← Catálogo · Capítulo 6

T06_CP01_mECO_IV_Educacion.R

Ver crudo
# =============================================================================
# TEMA 06 — CP1: IV — Retorno de la Educación
# =============================================================================
# Manual de Microeconometría — Carlos de Anta Puig
# Profesor de Econometría y Microeconometría — UNIR
# https://github.com/carlanta/MicroEconometrics  Versión 1.0 — 2026
#
# OBJETIVO: Estimar el retorno de la educación controlando la endogeneidad
#           por habilidad no observada. Instrumentos: educ. padre y madre.
#           Modelo sobreidentificado → test de Sargan aplicable.
# INSTRUCCIONES: Session > Set Working Directory > To Source File Location
# =============================================================================

pausa <- function(msg="\n>>> Pulsa ENTER para continuar...") {
  if (interactive()) readline(msg) else Sys.sleep(0.5)
}
pkgs <- c("AER","lmtest","sandwich")
for (p in pkgs) if (!requireNamespace(p, quietly=TRUE)) install.packages(p, quiet=TRUE)
suppressPackageStartupMessages({ library(AER); library(lmtest); library(sandwich) })
.get_script_dir <- function() {
  args <- commandArgs(trailingOnly = FALSE)
  for (a in args) {
    if (startsWith(a, "--file=")) return(dirname(normalizePath(substring(a, 8))))
  }
  for (i in seq_len(sys.nframe())) {
    ofile <- tryCatch(sys.frame(i)$ofile, error = function(e) NULL)
    if (!is.null(ofile)) return(dirname(normalizePath(ofile)))
  }
  return(normalizePath("."))
}
.sdir <- .get_script_dir()
DATA_DIR <- normalizePath(file.path(.sdir, "..", "data"), mustWork=FALSE)
OUTPUT_DIR <- normalizePath(file.path(.sdir, "..", "output"), mustWork=FALSE)
if (!dir.exists(OUTPUT_DIR)) dir.create(OUTPUT_DIR, recursive=TRUE)

cat("\n================================================================\n")
cat("  CP01 — Retorno de la Educación con IV\n")
cat("================================================================\n\n")

# --- CARGA Y DESCRIPCIÓN ---
load(file.path(DATA_DIR, "T06_CP01_retorno_educacion.RData"))
cat("Dataset:", nrow(educ_iv), "individuos\n\n")

cat("--- ESTADÍSTICOS DESCRIPTIVOS ---\n\n")
vars <- c("log_salario","anios_educacion","experiencia","educ_padre","educ_madre")
labs <- c("Log(salario)","Años educación","Experiencia","Educ. padre","Educ. madre")
cat(sprintf("  %-16s %8s %8s %8s %8s\n", "Variable","Media","D.E.","Mín.","Máx."))
cat(sprintf("  %s\n", paste(rep("-",54), collapse="")))
for (i in seq_along(vars)) {
  x <- educ_iv[[vars[i]]]
  cat(sprintf("  %-16s %8.2f %8.2f %8.1f %8.1f\n", labs[i],
              mean(x), sd(x), min(x), max(x)))
}
cat(sprintf("\n  Mujeres: %d (%.1f%%)\n",
            sum(educ_iv$sexo), 100*mean(educ_iv$sexo)))
cat(sprintf("  Regiones: %s\n", paste(names(table(educ_iv$region)), collapse=", ")))
pausa()

# --- EDA GRÁFICO ---
cat("\n--- ANÁLISIS EXPLORATORIO GRÁFICO ---\n\n")
png(file.path(OUTPUT_DIR, "T06_CP01_eda.png"), width=2000, height=700, res=150)
par(mfrow=c(1,3), mar=c(4.5,4.5,2.5,0.5), cex.main=0.82)

plot(educ_iv$anios_educacion, educ_iv$log_salario, pch=1, col=gray(0.5), cex=0.3,
     xlab="Años de educación", ylab="Log(salario)", main="Salario vs Educación")
abline(lm(log_salario ~ anios_educacion, data=educ_iv), lwd=2, lty=1)

plot(educ_iv$educ_padre, educ_iv$anios_educacion, pch=1, col=gray(0.5), cex=0.3,
     xlab="Educ. padre (años)", ylab="Educación individuo",
     main="1a etapa: padre")
abline(lm(anios_educacion ~ educ_padre, data=educ_iv), lwd=2, lty=1)

plot(educ_iv$educ_madre, educ_iv$anios_educacion, pch=1, col=gray(0.5), cex=0.3,
     xlab="Educ. madre (años)", ylab="Educación individuo",
     main="1a etapa: madre")
abline(lm(anios_educacion ~ educ_madre, data=educ_iv), lwd=2, lty=1)
dev.off()
cat("  Gráfico: output/T06_CP01_eda.png\n")
cat("  Los dos instrumentos muestran correlación positiva con educación.\n")
pausa()

# --- ESTIMACIÓN MCO ---
cat("\n--- ESTIMACIÓN MCO ---\n\n")
mco <- lm(log_salario ~ anios_educacion + experiencia + I(experiencia^2) + sexo,
           data=educ_iv)
s_mco <- summary(mco)
vv <- c("anios_educacion","experiencia","sexo")
labs_v <- c("Educación","Experiencia","Sexo (mujer)")
cat(sprintf("  %-16s | %9s %8s %8s %10s\n", "Variable","Coef.","EE","t","p-valor"))
cat(sprintf("  %s\n", paste(rep("-",58), collapse="")))
for (i in seq_along(vv)) {
  v <- vv[i]
  ct <- s_mco$coefficients
  sig <- ifelse(ct[v,4]<0.001,"***",ifelse(ct[v,4]<0.01,"**",
               ifelse(ct[v,4]<0.05,"*","   ")))
  cat(sprintf("  %-16s | %9.4f %8.4f %8.3f %10.6f %s\n",
              labs_v[i], ct[v,1], ct[v,2], ct[v,3], ct[v,4], sig))
}
cat(sprintf("\n  MCO: +1 año educ. = +%.1f%% salario\n", 100*coef(mco)["anios_educacion"]))
cat("  Este coeficiente INCLUYE el sesgo por habilidad omitida.\n")
pausa()

# --- PRIMERA ETAPA ---
cat("\n--- PRIMERA ETAPA (relevancia de los instrumentos) ---\n\n")
primera <- lm(anios_educacion ~ educ_padre + educ_madre + experiencia +
               I(experiencia^2) + sexo, data=educ_iv)
s_1st <- summary(primera)
cat(sprintf("  Coef. educ_padre: %.4f (p = %.4f)\n",
            coef(primera)["educ_padre"],
            s_1st$coefficients["educ_padre",4]))
cat(sprintf("  Coef. educ_madre: %.4f (p = %.4f)\n",
            coef(primera)["educ_madre"],
            s_1st$coefficients["educ_madre",4]))
cat(sprintf("  R² primera etapa: %.4f\n", s_1st$r.squared))
cat(sprintf("  F global: %.2f\n", s_1st$fstatistic[1]))
cat("\n  Ambos instrumentos son significativos individualmente.\n")
pausa()

# --- ESTIMACIÓN IV / MC2E ---
cat("\n--- ESTIMACIÓN IV (MC2E) ---\n\n")
iv <- ivreg(log_salario ~ anios_educacion + experiencia + I(experiencia^2) + sexo |
             educ_padre + educ_madre + experiencia + I(experiencia^2) + sexo,
             data=educ_iv)
s_iv <- summary(iv, diagnostics=TRUE)
ct_iv <- s_iv$coefficients

cat(sprintf("  %-16s | %9s %8s | %9s %8s\n", "Variable","MCO","EE","IV","EE"))
cat(sprintf("  %s\n", paste(rep("-",56), collapse="")))
for (i in seq_along(vv)) {
  v <- vv[i]
  cat(sprintf("  %-16s | %9.4f %8.4f | %9.4f %8.4f\n",
              labs_v[i], s_mco$coef[v,1], s_mco$coef[v,2],
              ct_iv[v,1], ct_iv[v,2]))
}
cat(sprintf("\n  IV: +1 año educ. = +%.1f%% salario (vs MCO: %.1f%%)\n",
            100*coef(iv)["anios_educacion"],
            100*coef(mco)["anios_educacion"]))
sesgo_pct <- 100*(coef(mco)["anios_educacion"] - coef(iv)["anios_educacion"])/
             coef(iv)["anios_educacion"]
cat(sprintf("  MCO sobreestima el retorno en un %.0f%%.\n", abs(sesgo_pct)))
pausa()

# --- DIAGNÓSTICOS ---
cat("\n--- DIAGNÓSTICOS IV ---\n\n")
diag_iv <- s_iv$diagnostics

cat("  1. INSTRUMENTOS DÉBILES (F primera etapa):\n")
if ("Weak instruments" %in% rownames(diag_iv)) {
  cat(sprintf("     F = %.2f (regla: F > 10)\n",
              diag_iv["Weak instruments",1]))
  if (diag_iv["Weak instruments",3] > 10)
    cat("     ✓ Instrumentos FUERTES.\n\n")
} else {
  cat(sprintf("     F primera etapa = %.2f\n", s_1st$fstatistic[1]))
  if (s_1st$fstatistic[1] > 10) cat("     ✓ Instrumentos FUERTES.\n\n")
}

cat("  2. TEST DE SARGAN (sobreidentificación):\n")
cat("     H0: Todos los instrumentos son válidos\n")
if ("Sargan" %in% rownames(diag_iv)) {
  cat(sprintf("     Estadístico: %.3f | p-valor: %.4f\n",
              diag_iv["Sargan",1], diag_iv["Sargan",4]))
  if (diag_iv["Sargan",4] > 0.05) {
    cat("     ✓ No se rechaza H0: instrumentos válidos.\n\n")
  } else {
    cat("     ✗ Se rechaza: al menos un instrumento no es válido.\n\n")
  }
}

cat("  3. TEST DE WU-HAUSMAN (endogeneidad):\n")
cat("     H0: educación es exógena (MCO suficiente)\n")
if ("Wu-Hausman" %in% rownames(diag_iv)) {
  cat(sprintf("     F = %.3f | p-valor: %.4f\n",
              diag_iv["Wu-Hausman",1], diag_iv["Wu-Hausman",4]))
  if (diag_iv["Wu-Hausman",4] < 0.05) {
    cat("     ✓ Se rechaza: educación ES endógena. IV necesario.\n\n")
  } else {
    cat("     ✗ No se rechaza. MCO podría ser suficiente.\n\n")
  }
}
pausa()

# --- GRÁFICO FINAL ---
png(file.path(OUTPUT_DIR, "T06_CP01_comparacion.png"), width=1200, height=600, res=150)
par(mar=c(5,8,2.5,1))
coefs_comp <- c(coef(mco)["anios_educacion"], coef(iv)["anios_educacion"])
ses_comp <- c(s_mco$coef["anios_educacion",2], ct_iv["anios_educacion",2])
bp <- barplot(rev(coefs_comp), horiz=TRUE, names.arg=rev(c("MCO","IV (2SLS)")),
              col=gray(c(0.4,0.7)), border="white",
              xlim=c(0, max(coefs_comp+2*ses_comp)*1.15),
              xlab="Coeficiente de educación", las=1,
              main="Sesgo de endogeneidad")
segments(rev(coefs_comp-1.96*ses_comp), bp,
         rev(coefs_comp+1.96*ses_comp), bp, lwd=2)
abline(v=0.07, lty=2, lwd=2, col=gray(0.3))
text(0.07, max(bp)+0.5, "Verdadero = 0.07", cex=0.7, pos=4)
dev.off()
cat("  Gráfico: output/T06_CP01_comparacion.png\n")
pausa()

# --- RESUMEN ---
cat("\n================================================================\n")
cat("  RESUMEN CP01 — Retorno de la Educación\n")
cat("================================================================\n\n")
cat(sprintf("  MCO: +1 año educ. = +%.1f%% salario (SESGADO)\n",
            100*coef(mco)["anios_educacion"]))
cat(sprintf("  IV:  +1 año educ. = +%.1f%% salario (CORREGIDO)\n",
            100*coef(iv)["anios_educacion"]))
cat(sprintf("  F primera etapa: %.0f (instrumentos fuertes)\n",
            s_1st$fstatistic[1]))
cat("  Los instrumentos (educ. padres) son fuertes y válidos.\n")
cat("  La habilidad omitida sesga MCO hacia arriba.\n")
cat("================================================================\n")