← Catálogo
· Capítulo 3
T03_CP02_mECO_Tobit_Donaciones.R
# =============================================================================
# TEMA 03 — CP2: Modelo Tobit — Donaciones Benéficas Anuales
# =============================================================================
# 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: Analizar los determinantes de las donaciones benéficas con Tobit.
# El 46.4% de la muestra no dona nada (censura en 0).
# 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")
for (p in pkgs) if (!requireNamespace(p,quietly=TRUE)) install.packages(p,quiet=TRUE)
suppressPackageStartupMessages({ library(AER); library(lmtest) })
.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)
cat("\n================================================================\n")
cat(" CP02 — Donaciones Benéficas: Modelo Tobit\n")
cat("================================================================\n\n")
load(file.path(DATA_DIR,"T03_CP02_donaciones.RData"))
cat("Dataset:", nrow(donaciones), "obs. |", ncol(donaciones), "variables\n")
n_d <- sum(donaciones$donacion==0)
cat(sprintf(" Ceros: %d (%.1f%%) | Media positivos: %.1f€\n\n",
n_d, 100*n_d/nrow(donaciones),
mean(donaciones$donacion[donaciones$donacion>0])))
cat("--- EDA RÁPIDA: medias por grupos ---\n\n")
for (v in c("ingreso","edad","religiosidad","educacion")) {
m0 <- mean(donaciones[[v]][donaciones$donacion==0])
m1 <- mean(donaciones[[v]][donaciones$donacion>0])
cat(sprintf(" %-15s | No dona: %5.2f | Dona: %5.2f | Dif: %+.2f\n",
v, m0, m1, m1-m0))
}
cat(sprintf(" %-15s | No dona: %4.1f%% | Dona: %4.1f%%\n",
"% con hijos",
100*mean(donaciones$tiene_hijos[donaciones$donacion==0]),
100*mean(donaciones$tiene_hijos[donaciones$donacion>0])))
pausa()
cat("\n--- ESTIMACIÓN MCO vs TOBIT ---\n\n")
fml_d <- donacion ~ ingreso + edad + religiosidad + educacion + tiene_hijos + sexo
mco_d <- lm(fml_d, data=donaciones)
tob_d <- AER::tobit(fml_d, left=0, data=donaciones)
ct_d <- coef(summary(tob_d))
vars_d <- c("ingreso","edad","religiosidad","educacion","tiene_hijos","sexo")
cat(" Variable | MCO | Tobit | Ratio\n")
cat(" -----------------------------------------------\n")
for (v in vars_d) {
sig <- ifelse(ct_d[v,4]<0.001,"***",ifelse(ct_d[v,4]<0.01,"**",
ifelse(ct_d[v,4]<0.05,"*"," ")))
cat(sprintf(" %-14s | %7.3f | %7.3f %s | %.2f\n", v,
coef(mco_d)[v], coef(tob_d)[v], sig,
coef(tob_d)[v]/coef(mco_d)[v]))
}
cat(sprintf(" sigma: | %-7s | %7.3f\n", "—", tob_d$scale))
pausa()
cat("\n--- EFECTOS MARGINALES AME ---\n\n")
beta_d <- coef(tob_d); sig_d <- tob_d$scale
xb_d <- predict(tob_d, newdata=donaciones, type="lp")
z_d <- xb_d / sig_d
Phi_d <- pnorm(z_d); imr_d <- dnorm(z_d)/Phi_d
ame_d <- mean(Phi_d) * beta_d[vars_d]
ame_cond <- mean(1-as.numeric(z_d)*as.numeric(imr_d)-as.numeric(imr_d)^2) * beta_d[vars_d]
cat(" Variable | AME E[y|x] | AME E[y|y>0]\n")
cat(" ---------------------------------------------------\n")
for (v in vars_d) {
cat(sprintf(" %-14s | %+10.3f | %+10.3f\n", v, ame_d[v], ame_cond[v]))
}
cat("\n▶ INTERPRETACIÓN CLAVE:\n")
cat(sprintf(" · Religiosidad: el predictor más potente (AME=%.2f€/año).\n",
ame_d["religiosidad"]))
cat(" Un punto más en el índice 0-5 aumenta la donación esperada\n")
cat(sprintf(" en %.2f€ por año. El efecto es muy superior al del ingreso.\n",
ame_d["religiosidad"]))
cat(sprintf(" · Ingreso: AME=%.2f€/año por cada €1.000 adicionales.\n",
ame_d["ingreso"]))
cat(sprintf(" · Hijos: tener hijos REDUCE la donación en %.2f€/año. Las\n",
abs(ame_d["tiene_hijos"])))
cat(" cargas familiares desplazan el gasto discrecional en donaciones.\n")
pausa()
cat("\n--- BONDAD DEL AJUSTE ---\n\n")
ll_0 <- as.numeric(logLik(glm(as.integer(donacion>0)~1, family=binomial, data=donaciones))) * 0
ll_n <- as.numeric(logLik(AER::tobit(donacion~1, left=0, data=donaciones)))
ll_m <- as.numeric(logLik(tob_d))
r2_mf <- 1 - ll_m/ll_n
lr_st <- -2*(ll_n - ll_m)
cat(sprintf(" Log-verosimilitud nulo: %.2f\n", ll_n))
cat(sprintf(" Log-verosimilitud modelo: %.2f\n", ll_m))
cat(sprintf(" McFadden R²: %.4f\n", r2_mf))
cat(sprintf(" Test LR (vs nulo): %.2f (p < 0.001)\n", lr_st))
cat(sprintf(" AIC: %.2f\n", AIC(tob_d)))
cat("\n================================================================\n")
cat(" FIN DEL SCRIPT T03_CP02_mECO_Tobit_Donaciones.R\n")
cat("================================================================\n\n")