← Catálogo
· Capítulo 6
T06_CP01_mECO_IV_Educacion.R
# =============================================================================
# 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")