1  Datos con Variable Dependiente Limitada

1.1 Cuando la variable dependiente no es libre

En la asignatura de econometría se aprende a estimar modelos de regresión lineal por MCO, donde la variable dependiente \(y\) podía tomar cualquier valor real: el salario, las ventas, el PIB. Sin embargo, en una proporción enorme de las aplicaciones microeconómicas, la variable que queremos explicar no es libre de tomar cualquier valor. Cuando su rango está restringido de alguna forma, hablamos de una variable dependiente limitada (limited dependent variable, LDV), y esa limitación tiene consecuencias profundas para la estimación.

Pensemos en tres situaciones concretas que todo economista aplicado encuentra de forma habitual. Cuando analizamos la participación laboral, la variable de interés es binaria: la persona trabaja o no trabaja, codificado como \(0\) o \(1\). Cuando estudiamos la elección de medio de transporte, la variable es multinomial: el viajero selecciona entre coche, autobús, tren o avión, y ninguna de esas opciones tiene un valor numérico intrínseco. Cuando modelamos el gasto en seguros médicos, la variable es continua pero censurada: muchas familias no gastan nada (el valor observado es exactamente cero), mientras que las demás presentan un gasto estrictamente positivo. En los tres casos, el modelo de regresión lineal clásico genera problemas graves que hacen inválida la inferencia estadística.

Este capítulo establece el mapa del territorio que recorreremos en el resto del manual. Presentamos los distintos tipos de variables dependientes limitadas, explicamos por qué MCO falla en cada caso y desarrollamos las distribuciones estadísticas que subyacen a cada familia de modelos. Al final del capítulo introducimos la caja de herramientas del análisis exploratorio de datos (EDA), que el alumno deberá aplicar sistemáticamente antes de estimar cualquier modelo.

1.1.1 Por qué MCO no es válido con variables dependientes limitadas

El modelo lineal clásico \(y_i = \mathbf{x}_i'\boldsymbol{\beta} + u_i\) produce predicciones \(\hat{y}_i = \mathbf{x}_i'\hat{\boldsymbol{\beta}}\) que pueden tomar cualquier valor en \(\mathbb{R}\). Cuando \(y_i\) solo puede ser \(0\) o \(1\), esto genera tres problemas simultáneos e irremediables.

En primer lugar, las predicciones son incoherentes: nada impide a MCO predecir probabilidades negativas o mayores que uno. Una probabilidad de \(-0.12\) o de \(1.34\) carece de interpretación. En segundo lugar, los errores son heterocedásticos por construcción: si \(y_i \in \{0,1\}\) y \(p_i = P(y_i=1 \mid \mathbf{x}_i)\), entonces \(\text{Var}(u_i) = p_i(1-p_i)\), que depende de \(\mathbf{x}_i\), violando de forma sistemática los supuestos del teorema de Gauss-Markov. En tercer lugar, los contrastes de hipótesis son inválidos: al no satisfacerse los supuestos distribucionales, los estadísticos \(t\) y \(F\) no siguen sus distribuciones teóricas en muestras finitas, lo que hace que los \(p\)-valores sean incorrectos.

Code
set.seed(2026)
n <- 200
x <- runif(n, -3, 6)
p_real <- pnorm(0.5 + 0.8 * x)
y <- rbinom(n, 1, p_real)
mlp <- lm(y ~ x)

par(mar = c(4.5, 4.5, 0.5, 1))
plot(x, y, pch = 1, col = gray(0.5),
     xlab = "Variable explicativa (x)", ylab = "y  /  Probabilidad predicha",
     ylim = c(-0.3, 1.35))
abline(mlp, lwd = 2.5, lty = 1, col = "black")
x_ord <- sort(x)
lines(x_ord, pnorm(0.5 + 0.8 * x_ord), lwd = 2.5, lty = 2, col = "black")
abline(h = c(0, 1), lty = 3, col = gray(0.4), lwd = 1)
rect(-4, -0.45, 8, 0, col = gray(0.92), border = NA)
rect(-4, 1, 8, 1.5, col = gray(0.92), border = NA)
text(5, -0.18, "Zona imposible\n(prob. < 0)", col = gray(0.2), cex = 0.75, font = 3)
text(5, 1.18, "Zona imposible\n(prob. > 1)", col = gray(0.2), cex = 0.75, font = 3)
legend("topleft",
       legend = c("MCO: predicciones fuera de [0,1]",
                  "Probit: siempre dentro de [0,1]",
                  "Límites 0 y 1"),
       lwd = c(2.5, 2.5, 1), lty = c(1, 2, 3),
       col = c("black", "black", gray(0.4)), bty = "n", cex = 0.8)
Figure 1.1: El modelo lineal de probabilidad (MCO) aplicado a una variable binaria produce predicciones fuera del intervalo [0, 1] — zonas sombreadas — mientras que el modelo Probit correcto mantiene las predicciones dentro del rango válido.

La Figure 1.1 lo ilustra sin ambigüedad: la recta de MCO traspasa las barreras naturales de la probabilidad. El modelo Probit, en cambio, utiliza la función de distribución acumulada de la Normal para garantizar que todas las predicciones estén en \([0,1]\). Cuando la variable dependiente está limitada, necesitamos modelos que respeten esas restricciones por diseño.

1.2 La taxonomía de las variables dependientes limitadas

Las variables dependientes limitadas se organizan en tres grandes familias según la naturaleza de la restricción que sufre \(y_i\). La clasificación no es meramente académica: cada familia conduce a un tipo de modelo diferente, y entender bien esta arquitectura es el primer paso para elegir la herramienta correcta ante un problema econométrico real.

La primera familia comprende las variables binarias o dicotómicas, donde \(y_i \in \{0, 1\}\). La restricción es total: solo existen dos resultados posibles. El decisor trabaja o no trabaja, contrata o no contrata, compra o no compra. Los modelos apropiados son el Probit y el Logit, que estudiaremos en el Chapter 2.

La segunda familia son las variables multinomiales, donde \(y_i \in \{0, 1, \ldots, J\}\) con \(J \geq 2\). Dentro de esta familia se distingue entre variables ordenadas — el nivel de satisfacción va de 1 a 5, y existe un orden natural entre las categorías — y variables no ordenadas, como la elección de modo de transporte, donde las categorías no tienen jerarquía. Esta familia exige modelos de elección múltiple que van más allá del alcance de este manual.

La tercera familia son las variables continuas limitadas, donde \(y_i\) es continua pero solo puede tomar valores en un subconjunto de \(\mathbb{R}\): típicamente \(y_i \geq 0\) (censura por la izquierda en cero). El gasto en seguros, las horas trabajadas y la cantidad demandada de un bien son ejemplos clásicos. El modelo Tobit y sus extensiones son la herramienta adecuada, desarrollada en el el Capítulo 3.

Una cuarta familia, que comparte rasgos con la anterior, son las variables de recuento: \(y_i \in \{0, 1, 2, \ldots\}\), donde \(y_i\) solo toma valores enteros no negativos. El número de visitas al médico, el número de accidentes de tráfico o el número de patentes son ejemplos habituales. Los modelos de Poisson y Binomial Negativa son los instrumentos adecuados, objeto del el Capítulo 4.

Code
par(mar = c(0.5, 0.5, 0.5, 0.5))
plot(NULL, xlim = c(0, 10), ylim = c(0, 7.5),
     xlab = "", ylab = "", xaxt = "n", yaxt = "n", bty = "n")

# Raíz
rect(2.8, 6.2, 7.2, 7.2, col = gray(0.15), border = NA)
text(5, 6.7, "Variable dependiente\nlimitada", col = "white", font = 2, cex = 0.85)

# Ramas
cols_ramas <- gray(c(0.25, 0.45, 0.65, 0.80))
rect(0.1, 4.2, 2.6, 5.5, col = cols_ramas[1], border = NA)
text(1.35, 5.0, "Binaria", col = "white", font = 2, cex = 0.8)
text(1.35, 4.5, "y in {0, 1}", col = gray(0.9), cex = 0.7)

rect(3.0, 4.2, 5.5, 5.5, col = cols_ramas[2], border = NA)
text(4.25, 5.0, "Multinomial", col = "white", font = 2, cex = 0.8)
text(4.25, 4.5, "y in {0,...,J}", col = gray(0.9), cex = 0.7)

rect(5.9, 4.2, 8.0, 5.5, col = cols_ramas[3], border = NA)
text(6.95, 5.0, "Censurada", col = "white", font = 2, cex = 0.8)
text(6.95, 4.5, "y >= 0", col = gray(0.9), cex = 0.7)

rect(8.3, 4.2, 9.9, 5.5, col = cols_ramas[4], border = NA)
text(9.1, 5.0, "Recuento", col = "white", font = 2, cex = 0.8)
text(9.1, 4.5, "y = 0,1,2,...", col = gray(0.9), cex = 0.7)

# Flechas
segments(5, 6.2, 5, 5.8, lwd = 1.5)
segments(1.35, 5.8, 9.1, 5.8, lwd = 1.5)
segments(c(1.35,4.25,6.95,9.1), 5.8, c(1.35,4.25,6.95,9.1), 5.5, lwd=1.5)

# Modelos
rect(0.1, 2.4, 2.6, 3.8, col = gray(0.88), border = gray(0.3), lwd = 1)
text(1.35, 3.3, "Probit / Logit", font = 2, cex = 0.7, col = gray(0.1))
text(1.35, 2.8, "Cap. 2", cex = 0.65, col = gray(0.3))
segments(1.35, 4.2, 1.35, 3.8, lwd=1, lty=2, col=gray(0.4))

rect(3.0, 2.4, 5.5, 3.8, col = gray(0.88), border = gray(0.3), lwd = 1)
text(4.25, 3.3, "Logit multinomial\nProbit ordenado", font = 2, cex = 0.65, col = gray(0.1))
text(4.25, 2.75, "(Temas avanzados)", cex = 0.6, col = gray(0.3))
segments(4.25, 4.2, 4.25, 3.8, lwd=1, lty=2, col=gray(0.4))

rect(5.9, 2.4, 8.0, 3.8, col = gray(0.88), border = gray(0.3), lwd = 1)
text(6.95, 3.3, "Tobit", font = 2, cex = 0.7, col = gray(0.1))
text(6.95, 2.8, "Cap. 3", cex = 0.65, col = gray(0.3))
segments(6.95, 4.2, 6.95, 3.8, lwd=1, lty=2, col=gray(0.4))

rect(8.3, 2.4, 9.9, 3.8, col = gray(0.88), border = gray(0.3), lwd = 1)
text(9.1, 3.3, "Poisson / NB", font = 2, cex = 0.7, col = gray(0.1))
text(9.1, 2.8, "Cap. 4", cex = 0.65, col = gray(0.3))
segments(9.1, 4.2, 9.1, 3.8, lwd=1, lty=2, col=gray(0.4))

# Ejemplos
text(1.35, 1.8, "Trabaja / no trabaja\nCompra / no compra", cex = 0.65, col=gray(0.2))
text(4.25, 1.8, "Modo de transporte\nNivel de satisfacción", cex = 0.65, col=gray(0.2))
text(6.95, 1.8, "Gasto seguros\nHoras trabajadas", cex = 0.65, col=gray(0.2))
text(9.1, 1.8, "Visitas al médico\nAccidentes", cex = 0.65, col=gray(0.2))
Figure 1.2: Clasificación de las variables dependientes limitadas. Cada familia conduce a una familia de modelos diferente. Las flechas indican el capítulo del manual donde se desarrolla cada modelo.

1.3 Variables binarias: la decisión sí o no

1.3.1 La distribución de Bernoulli

Una variable dependiente binaria solo puede tomar dos valores: \(y_i = 1\) si ocurre el evento de interés (trabajar, comprar, aprobar), \(y_i = 0\) en caso contrario. Estadísticamente, sigue una distribución Bernoulli(p):

\[P(y = 1) = p \qquad P(y = 0) = 1 - p\]

En forma compacta, la función de masa de probabilidad es \(f(y;\,p) = p^{\,y}\,(1-p)^{1-y}\) con \(y \in \{0,1\}\). Sus momentos son \(E(y) = p\) y \(\text{Var}(y) = p(1-p)\). El hecho de que la varianza dependa de \(p\) — que a su vez depende de \(\mathbf{x}_i\) en cualquier modelo econométrico — confirma directamente que la homocedasticidad se viola de forma inherente con variables binarias. No es un fallo del modelo: es una característica matemática de la distribución Bernoulli.

La clave de los modelos que construiremos en el siguiente capítulo es hacer que \(p\) no sea la misma para todos los individuos, sino que varíe en función de sus características observables: \(p_i = F(\mathbf{x}_i'\boldsymbol{\beta})\), donde \(F\) es una función de distribución acumulada que garantiza \(p_i \in [0,1]\) para cualquier valor del índice lineal \(\mathbf{x}_i'\boldsymbol{\beta}\).

Code
par(mfrow = c(1, 3), mar = c(5.5, 4, 2.5, 0.5))
for (p in c(0.2, 0.5, 0.8)) {
  bp <- barplot(c(1-p, p), names.arg = c("y = 0\n(no ocurre)", "y = 1\n(ocurre)"),
          col = gray(c(0.75, 0.30)), border = "white",
          ylim = c(0, 1.1), ylab = "Probabilidad",
          main = bquote(Bernoulli(p == .(p))))
  abline(h = 0)
  text(bp[1], 1-p+0.05, sprintf("%.1f", 1-p), font=2, cex=0.9)
  text(bp[2], p+0.05, sprintf("%.1f", p), font=2, cex=0.9)
  mtext(bquote(Var == .(round(p*(1-p),3))), side=1, line=4.5, cex=0.75)
}
par(mfrow = c(1, 1))
Figure 1.3: Distribución Bernoulli para tres valores del parámetro p. A medida que p aumenta, la probabilidad de observar y = 1 crece. Obsérvese que la varianza p(1-p) es máxima en p = 0.5 (barras de igual altura).

1.3.2 La distribución Binomial

Si en lugar de observar a un individuo observamos a \(n\) individuos independientes con la misma probabilidad \(p\), el número total de éxitos \(k = \sum_{i=1}^n y_i\) sigue una distribución Binomial(n, p):

\[\boxed{P(k;\,n,p) = \binom{n}{k}\,p^k\,(1-p)^{n-k}, \qquad k = 0, 1, \ldots, n}\]

con media \(E(k) = np\) y varianza \(\text{Var}(k) = np(1-p)\). La Bernoulli es el caso particular \(n=1\). La función de verosimilitud de los modelos Logit y Probit se construye precisamente como el producto de \(n\) densidades Bernoulli independientes, de manera que la estimación por Máxima Verosimilitud maximiza la probabilidad conjunta de haber observado el conjunto de ceros y unos que vemos en la muestra.

Code
library(kableExtra)
k_vals <- 0:10
p_masa <- dbinom(k_vals, 10, 0.5)
p_acum <- pbinom(k_vals, 10, 0.5)
comb   <- choose(10, k_vals)
df_binom <- data.frame(
  k          = k_vals,
  Combinaciones = formatC(comb, format="d", big.mark="."),
  `P(X=k)`   = sprintf("%.4f", p_masa),
  `P(X=k) %` = sprintf("%.2f%%", p_masa*100),
  `P(X<=k)`  = sprintf("%.4f", p_acum),
  check.names = FALSE
)
kbl(df_binom, booktabs=TRUE, align=c("c","r","c","c","c"),
    col.names=c("k","C(10,k)","P(X=k)","P(X=k)%","P(X≤k)")) |>
  kable_styling(latex_options=c("hold_position","scale_down"),
                bootstrap_options=c("striped","condensed"), full_width=FALSE) |>
  row_spec(6, bold=TRUE, background="#f0f0f0")
Table 1.1: Distribución Binomial(10, 0.5): probabilidad de obtener exactamente k caras al lanzar 10 monedas justas. La columna ‘Acumulada’ muestra P(X ≤ k).
k C(10,k) P(X=k) P(X=k)% P(X≤k)
0 1 0.0010 0.10% 0.0010
1 10 0.0098 0.98% 0.0107
2 45 0.0439 4.39% 0.0547
3 120 0.1172 11.72% 0.1719
4 210 0.2051 20.51% 0.3770
5 252 0.2461 24.61% 0.6230
6 210 0.2051 20.51% 0.8281
7 120 0.1172 11.72% 0.9453
8 45 0.0439 4.39% 0.9893
9 10 0.0098 0.98% 0.9990
10 1 0.0010 0.10% 1.0000

La Table 1.1 muestra que, lanzando 10 monedas justas, la probabilidad más alta corresponde a obtener exactamente 5 caras (resaltada), con una probabilidad del 24.61%. Las probabilidades decaen simétricamente a ambos lados del centro, reflejo de que \(p = 0.5\) hace la distribución perfectamente simétrica.

1.3.3 La variable latente: el mecanismo que no vemos

En muchos problemas económicos, la variable que realmente determina el comportamiento del individuo no es directamente observable. Cuando una persona decide si participar en el mercado laboral, lo que determina esa decisión es la utilidad neta de trabajar: la diferencia entre el beneficio percibido (salario, realización personal, vida social) y el coste (esfuerzo, desplazamiento, cuidado de hijos). Esa utilidad neta no la observamos, pero sí observamos la decisión que toma.

El enfoque de variable latente formaliza esta idea econométricamente. Definimos la variable no observable:

\[y_i^* = \mathbf{x}_i'\boldsymbol{\beta} + u_i\]

y establecemos la regla de decisión:

\[y_i = \begin{cases} 1 & \text{si } y_i^* > 0 \\ 0 & \text{si } y_i^* \leq 0 \end{cases}\]

A partir de esta regla, la probabilidad de observar \(y_i = 1\) es:

\[P(y_i = 1 \mid \mathbf{x}_i) = P(y_i^* > 0 \mid \mathbf{x}_i) = P(u_i > -\mathbf{x}_i'\boldsymbol{\beta}) = F(\mathbf{x}_i'\boldsymbol{\beta})\]

donde \(F\) es la función de distribución acumulada del término de error. Si \(u_i \sim N(0,1)\), \(F = \Phi\) y el modelo es Probit. Si \(u_i\) sigue una distribución Logística estándar, \(F = \Lambda\) (función logística) y el modelo es Logit. La elección entre Probit y Logit radica, por tanto, en el supuesto distribucional que hacemos sobre el término de error de la ecuación latente.

Code
set.seed(42)
n <- 150
x_lat <- seq(-3, 3, length.out=n)
y_star <- 0.5 + 1.2*x_lat + rnorm(n, 0, 1.5)
y_obs  <- as.integer(y_star > 0)

par(mfrow=c(1,2), mar=c(4.5, 4.5, 2, 0.5))

# Panel 1: variable latente
plot(x_lat, y_star,
     pch  = ifelse(y_star > 0, 16, 1),
     col  = ifelse(y_star > 0, gray(0.2), gray(0.6)),
     xlab = "x", ylab = expression(y^"*"~(variable~latente)),
     main = expression("Variable latente"~y^"*"))
abline(h=0, lty=2, lwd=1.5, col=gray(0.4))
abline(a=0.5, b=1.2, lwd=2, lty=1, col="black")
text( 2.0, -3.8, "y* ≤ 0  ⇒  y = 0", col=gray(0.3), cex=0.75, font=3)
text(-2.5,  4.5, "y* > 0  ⇒  y = 1", col=gray(0.1), cex=0.75, font=3)
legend("topleft", legend=c(expression(y==1), expression(y==0)),
       pch=c(16,1), col=c(gray(0.2),gray(0.6)), bty="n", cex=0.8)

# Panel 2: variable observada + curva probit
plot(x_lat, y_obs,
     pch  = ifelse(y_obs==1, 16, 1),
     col  = ifelse(y_obs==1, gray(0.2), gray(0.6)),
     xlab = "x", ylab = "y  (variable observada)",
     main = "Variable observada y", yaxt="n", ylim=c(-0.1,1.1))
axis(2, at=c(0,1), labels=c("0","1"))
lines(sort(x_lat), pnorm(0.5 + 1.2*sort(x_lat), 0, 1.5), lwd=2.5, lty=1)
text(1.5, 0.38, expression(P(y==1~"|"~x)), cex=0.8, font=2)

par(mfrow=c(1,1))
Figure 1.4: El enfoque de variable latente. Panel izquierdo: la variable latente y* (utilidad neta) es continua e inobservable. Panel derecho: solo observamos la decisión binaria y, que es 1 cuando y* supera el umbral de cero. La curva S muestra cómo P(y=1|x) crece con x siguiendo la CDF normal (Probit).

La Figure 1.4 ilustra perfectamente la transformación: en el panel izquierdo, la variable latente \(y^*\) es continua y puede tomar cualquier valor real; los puntos oscuros (rellenos) son los individuos con \(y^* > 0\) y los puntos grises (huecos) los que tienen \(y^* \leq 0\). En el panel derecho, solo vemos la decisión binaria \(y\), pero la curva en S del Probit recupera la estructura probabilística subyacente.

1.4 Variables multinomiales: más de dos opciones

Cuando la variable dependiente puede tomar más de dos categorías, entramos en el terreno de las variables multinomiales. La distinción fundamental es si esas categorías tienen un orden natural o no. Las variables ordenadas — como el nivel de satisfacción codificado de 1 a 5, o la calificación crediticia de AAA a D — tienen categorías con un orden claro pero distancias no definidas entre ellas. Las variables no ordenadas — como la elección de medio de transporte o el sector de empleo — no tienen ningún orden implícito entre sus categorías.

En ambos casos, el modelo subyacente postula que cada individuo elige la alternativa que le proporciona mayor utilidad: \(y_i = j\) si \(U_{ij} > U_{ik}\) para todo \(k \neq j\), donde \(U_{ij}\) es la utilidad que el individuo \(i\) obtendría de elegir la alternativa \(j\). Los modelos para estas situaciones (Logit multinomial, Probit ordenado) son extensiones de los modelos binarios que desarrollaremos en el siguiente capítulo, pero su estudio detallado queda fuera del alcance de este manual introductorio.

Lo que sí es importante retener desde ahora es la distribución Multinomial, que generaliza la Binomial a más de dos categorías. Con \(n\) ensayos y \(J+1\) categorías con probabilidades \(p_0, p_1, \ldots, p_J\) (con \(\sum_{j=0}^J p_j = 1\)):

\[\boxed{P(k_0, k_1, \ldots, k_J) = \frac{n!}{k_0!\,k_1!\cdots k_J!}\,p_0^{k_0}\,p_1^{k_1}\cdots p_J^{k_J}}\]

La jerarquía es clara: la Multinomial con \(J=1\) y \(n\) ensayos es la Binomial; la Binomial con \(n=1\) es la Bernoulli. Cada distribución es un caso particular de la siguiente en esta cadena de generalización.

Code
set.seed(2026)
probs <- c(Coche=0.45, Autobús=0.25, Tren=0.20, Avión=0.10)
elecciones <- sample(names(probs), 1000, replace=TRUE, prob=probs)
freq <- table(factor(elecciones, levels=names(probs)))
prop <- prop.table(freq)

par(mar=c(4.5, 4.5, 0.5, 1))
bp <- barplot(prop,
        col    = gray(c(0.15, 0.40, 0.65, 0.85)),
        border = "white",
        ylim   = c(0, 0.55),
        ylab   = "Proporción muestral",
        xlab   = "Medio de transporte",
        names.arg = names(prop))
abline(h=0)
points(bp, as.numeric(probs), pch=17, cex=1.4, col="black")
segments(bp, as.numeric(prop), bp, as.numeric(probs), lty=2, col=gray(0.4))
text(bp, as.numeric(prop)+0.025, sprintf("%.1f%%", as.numeric(prop)*100), font=2, cex=0.85)
legend("topright", legend=c("Frecuencia observada","Probabilidad teórica"),
       fill=c(gray(0.5),NA), pch=c(NA,17), border=c("white",NA),
       col=c(NA,"black"), bty="n", cex=0.8)
Figure 1.5: Elección de medio de transporte para 1000 viajeros simulados. La distribución Multinomial asigna una probabilidad a cada categoría; la frecuencia observada converge a esas probabilidades con el aumento del tamaño muestral.

En la Figure 1.5, los triángulos muestran las probabilidades teóricas y las barras las frecuencias observadas. Con \(n=1000\) la convergencia es razonablemente buena, aunque persisten pequeñas desviaciones muestrales.

1.5 Variables continuas limitadas: censura y truncamiento

Hasta ahora hemos visto variables que toman valores discretos. Pero también existen variables dependientes continuas cuyo rango está restringido. Esto sucede por dos mecanismos distintos que es fundamental no confundir: la censura y el truncamiento. Aunque superficialmente parecidos, tienen consecuencias econométricas y soluciones completamente diferentes.

En la censura, la variable latente \(y_i^*\) existe para todos los individuos de la población, pero cuando \(y_i^*\) cae por debajo (o encima) de un umbral \(c\), solo observamos el valor \(c\) en lugar del verdadero \(y_i^*\). Crucialmente, seguimos observando las covariables \(\mathbf{x}_i\) de todos los individuos, incluyendo los que tienen \(y_i = c\). El gasto en seguros médicos es el ejemplo canónico: todas las familias tienen un nivel “deseado” de cobertura, pero las que no pueden permitírsela (o no lo desean) tienen un gasto observado de cero. Observamos su renta, edad y composición del hogar; simplemente no podemos saber cuánto gastarían si su situación fuera diferente.

En el truncamiento, los individuos cuya \(y_i^*\) cae fuera del rango observable desaparecen completamente de la muestra: no observamos ni su \(y\) ni sus \(\mathbf{x}\). Un estudio de salarios para trabajadores con salario mínimo, que excluye a todos los desempleados, es un ejemplo de truncamiento: las personas que querrían trabajar pero no encuentran trabajo a ese salario simplemente no aparecen en los datos.

La distinción es crucial porque el truncamiento genera un sesgo de selección más difícil de corregir: ni siquiera sabemos cuántos individuos faltan ni cuáles son sus características. Con la censura, al menos tenemos esa información parcial.

Code
set.seed(2026)
n <- 300
x_tr <- runif(n, 0, 10)
y_star_tr <- -2 + 1.5*x_tr + rnorm(n, 0, 2)
sel <- y_star_tr > 0

par(mfrow=c(1,2), mar=c(4.5, 4.5, 2, 0.5))

# Censura
y_cens <- pmax(y_star_tr, 0)
plot(x_tr, y_cens, pch=ifelse(y_star_tr>0, 16, 1),
     col=ifelse(y_star_tr>0, gray(0.25), gray(0.65)),
     xlab="x", ylab="y", main="Censura en 0")
abline(h=0, lty=2, col=gray(0.4))
abline(lm(y_cens ~ x_tr), lwd=2, lty=1, col="black")
abline(a=-2, b=1.5, lwd=2, lty=2, col="black")
legend("topleft", legend=c("y>0 (observado)","y=0 (censurado)",
                            "MCO (sesgado)","Línea verdadera"),
       pch=c(16,1,NA,NA), lty=c(NA,NA,1,2), lwd=c(NA,NA,2,2),
       col=c(gray(0.25),gray(0.65),"black","black"), bty="n", cex=0.7)

# Truncamiento
plot(x_tr[sel], y_star_tr[sel], pch=16, col=gray(0.25),
     xlab="x", ylab="y", main="Truncamiento en 0",
     xlim=range(x_tr), ylim=range(y_star_tr))
abline(h=0, lty=2, col=gray(0.4))
rect(par("usr")[1], par("usr")[3], par("usr")[2], 0,
     col=gray(0.93), border=NA)
text(5, -2.5, "Datos perdidos\n(no observados)", cex=0.75, font=3, col=gray(0.4))
abline(a=-2, b=1.5, lwd=2, lty=2, col="black")

par(mfrow=c(1,1))
Figure 1.6: Censura (panel izquierdo) frente a truncamiento (panel derecho). En la censura conocemos x para todos, pero y se observa como 0 para los individuos con y* ≤ 0 (puntos huecos). En el truncamiento, esos individuos desaparecen completamente de la muestra.

La Figure 1.6 pone de manifiesto la diferencia. En la censura (izquierda), MCO con los datos observados produce una recta sesgada (sólida) que subestima la pendiente verdadera (discontinua), porque trata los ceros de censura como si fueran valores reales. En el truncamiento (derecha), directamente no disponemos de las observaciones en la zona gris, y la recta verdadera apenas puede recuperarse sin corrección estadística.

Code
set.seed(2026)
n_h <- 400
renta_h <- runif(n_h, 15, 80)
gasto_lat <- -20 + 0.55*renta_h + rnorm(n_h, 0, 8)
gasto_obs <- pmax(gasto_lat, 0)
n_ceros   <- sum(gasto_obs == 0)

par(mar=c(4.5, 4.5, 0.5, 1))
hist(gasto_obs, breaks=30, col=gray(0.70), border="white",
     main="", xlab="Gasto observado en seguros (€/mes)", ylab="Frecuencia",
     xlim=c(-3, max(gasto_obs)))
abline(v=0.5, lty=2, col=gray(0.3))
text(1.5, n_ceros*0.55,
     sprintf("%d obs.\ncensuradas\nen y=0", n_ceros),
     col=gray(0.1), font=2, cex=0.8, pos=4)
arrows(1.2, n_ceros*0.42, 0.3, n_ceros*0.25, length=0.08, col=gray(0.1), lwd=1.5)
Figure 1.7: Distribución del gasto en seguros en una muestra simulada con censura en cero. La distribución presenta dos componentes: una masa de probabilidad en y = 0 (barra izquierda aislada) y una distribución continua para los valores positivos. Esta estructura mixtaes precisamente la que motiva el modelo Tobit.

1.6 El análisis exploratorio de datos como primer paso

Antes de estimar cualquier modelo econométrico, el primer paso es siempre conocer los datos. No hay ningún modelo estadístico que pueda compensar el desconocimiento de la estructura, los outliers, las distribuciones y las relaciones entre las variables de la muestra. El análisis exploratorio de datos (EDA, por sus siglas en inglés) es la herramienta que nos permite hacer ese diagnóstico previo de forma sistemática y rigurosa.

El EDA no es un trámite burocrático. Es la fase en la que el econometrista desarrolla intuición sobre el problema, detecta anomalías en los datos, identifica el tipo de variable dependiente que tiene entre manos y anticipa qué modelos serán apropiados. En este manual, el EDA aparecerá siempre como primera sección de cada análisis, antes de cualquier estimación. Este capítulo presenta las herramientas básicas que se usarán de forma repetida a lo largo de todo el curso.

1.6.1 Carga e inspección inicial de los datos

El punto de partida de cualquier análisis es leer los datos y verificar su estructura. En R, las funciones básicas son load() para archivos .RData, read.csv() para texto plano, str() para ver la estructura interna, y summary() para obtener un primer resumen estadístico.

Code
load("data/T01_CP01_empleo_basico.RData")
library(kableExtra)

# Mostramos las 6 primeras filas formateadas
df_head <- head(empleo, 6)
df_head$sector[is.na(df_head$sector)] <- "—"
df_head$salario_bruto <- ifelse(is.na(df_head$salario_bruto), "—",
                                sprintf("%.1f", df_head$salario_bruto))
kbl(df_head, booktabs=TRUE,
    col.names=c("Trabaja","Edad","Educ.","Exper.","Sexo","Hijos","Salario €/h","Sector"),
    align=c("c","c","c","c","c","c","r","l")) |>
  kable_styling(latex_options=c("hold_position","scale_down"),
                bootstrap_options=c("condensed","striped"), full_width=FALSE) |>
  footnote(general="Educación y experiencia en años; salario en €/hora. — = no aplica.",
           general_title="Nota:", footnote_as_chunk=FALSE)
Table 1.2: Estructura del dataset de mercado laboral (CP01). Las seis primeras observaciones muestran la naturaleza de cada variable: trabaja es binaria (0/1), salario_bruto es continua con NAs para los no empleados, y sector es categórica.
Trabaja Edad Educ. Exper. Sexo Hijos Salario €/h Sector
1 60 12 42 1 1 32.0 Agricultura
0 30 16 8 0 0
1 26 6 14 0 2 17.6 Servicios
1 42 11 25 0 0 22.1 Agricultura
1 23 9 8 1 0 18.1 Agricultura
0 41 14 21 0 0
Nota:
Educación y experiencia en años; salario en €/hora. — = no aplica.

Una vez cargados los datos, lo primero es verificar que el número de observaciones, el número de variables y los tipos de datos son los esperados. El siguiente código produce un resumen estadístico que conviene mirar siempre antes de continuar:

Code
vars_num <- c("edad","educacion","experiencia","hijos","salario_bruto")
desc <- sapply(empleo[, vars_num], function(v) {
  c(Media   = round(mean(v, na.rm=TRUE), 2),
    Mediana = round(median(v, na.rm=TRUE), 2),
    DT      = round(sd(v, na.rm=TRUE), 2),
    Min     = round(min(v, na.rm=TRUE), 2),
    Max     = round(max(v, na.rm=TRUE), 2),
    NAs     = sum(is.na(v)))
})
df_desc <- as.data.frame(t(desc))
df_desc$Variable <- c("Edad (años)","Educación (años)","Experiencia (años)",
                       "Número de hijos","Salario (€/hora)")
df_desc <- df_desc[, c("Variable", setdiff(names(df_desc),"Variable"))]
kbl(df_desc, booktabs=TRUE, row.names=FALSE,
    col.names=c("Variable","Media","Mediana","D.T.","Mín.","Máx.","NAs")) |>
  kable_styling(latex_options=c("hold_position","scale_down"),
                bootstrap_options=c("condensed","striped"), full_width=FALSE)
Table 1.3: Estadísticos descriptivos del dataset de mercado laboral. La columna NA muestra los valores ausentes, presentes únicamente en las variables sólo observables para trabajadores (salario, sector). La tasa de empleo es del 58.2%.
Variable Media Mediana D.T. Mín. Máx. NAs
Edad (años) 41.96 42.00 13.50 20.00 65.00 0
Educación (años) 11.98 12.00 3.04 6.00 21.00 0
Experiencia (años) 24.00 24.00 13.61 0.00 52.00 0
Número de hijos 1.24 1.00 1.11 0.00 6.00 0
Salario (€/hora) 26.76 26.63 4.68 15.39 37.34 251

La Table 1.3 revela inmediatamente dos características esenciales del dataset. Por un lado, salario_bruto tiene valores ausentes, exactamente los correspondientes a las personas que no trabajan — un patrón perfectamente esperado y que no constituye un problema de calidad de datos, sino una consecuencia natural del mecanismo de generación de los datos. Por otro lado, la experiencia media es de unos 15 años, lo que es coherente con una muestra de adultos en edad laboral.

1.6.2 Análisis visual de distribuciones univariantes

Para cada variable cuantitativa conviene examinar siempre su distribución completa, no solo sus estadísticos resumen. El histograma y el diagrama de caja (boxplot) son las herramientas más inmediatas. El histograma revela la forma de la distribución (simetría, sesgos, modas, outliers), mientras que el boxplot facilita la comparación entre grupos.

El diagrama de caja-y-bigotes representa: la mediana (línea central), el rango intercuartílico IQR = Q3-Q1 (caja), los bigotes hasta \(1.5 \times \text{IQR}\) desde los cuartiles, y los puntos individuales que caen más allá de los bigotes (outliers potenciales).

Code
par(mfrow=c(2,3), mar=c(4,4,2,0.5))

# Edad
hist(empleo$edad, col=gray(0.75), border="white",
     main="Edad", xlab="Años", ylab="Frecuencia", breaks=15)
abline(v=mean(empleo$edad), lty=2, lwd=1.5, col="black")

# Educación
hist(empleo$educacion, col=gray(0.75), border="white",
     main="Educación", xlab="Años", ylab="Frecuencia", breaks=10)
abline(v=mean(empleo$educacion), lty=2, lwd=1.5, col="black")

# Experiencia
hist(empleo$experiencia, col=gray(0.75), border="white",
     main="Experiencia", xlab="Años", ylab="Frecuencia", breaks=15)
abline(v=mean(empleo$experiencia), lty=2, lwd=1.5, col="black")

# Hijos
barplot(table(empleo$hijos), col=gray(0.70), border="white",
        main="Número de hijos", xlab="Hijos", ylab="Frecuencia")

# Salario (solo empleados)
sal_emp <- empleo$salario_bruto[!is.na(empleo$salario_bruto)]
hist(sal_emp, col=gray(0.75), border="white",
     main="Salario (empleados)", xlab="€/hora", ylab="Frecuencia", breaks=15)
abline(v=mean(sal_emp), lty=2, lwd=1.5, col="black")

# Boxplot salario por sexo
boxplot(salario_bruto ~ sexo, data=empleo[!is.na(empleo$salario_bruto),],
        names=c("Mujer","Hombre"), col=gray(c(0.80,0.55)),
        main="Salario por sexo", ylab="€/hora", xlab="")

par(mfrow=c(1,1))
Figure 1.8: Distribuciones de las variables cuantitativas del dataset de mercado laboral. El histograma de edad muestra una distribución aproximadamente uniforme entre 20 y 65 años. Educación presenta una distribución unimodal centrada en 12 años. La experiencia tiene sesgo positivo. El boxplot de salario, calculado solo para empleados, muestra la presencia de algunos outliers por la derecha (trabajadores con salarios altos).

Las líneas discontinuas verticales en los histogramas marcan la media de cada variable. En la Figure 1.8 se pueden observar varios patrones relevantes. La distribución de experiencia tiene un sesgo positivo notable — hay pocas personas con experiencia muy elevada pero su cola derecha es larga — lo que sugiere que en modelos con esta variable podría ser útil considerar una transformación logarítmica. El boxplot de salario por sexo anticipa una brecha salarial que será objeto de análisis en capítulos posteriores.

1.6.3 Análisis de la variable dependiente: patrones por tipo de VDL

El análisis de la variable dependiente merece atención especial porque su naturaleza determina el modelo a usar. Antes de examinar la relación entre \(y\) y las covariables, hay que entender la distribución marginal de \(y\).

Code
par(mfrow=c(1,2), mar=c(4,4.5,2.5,0.5), cex.main=0.84)

# Panel 1: distribución marginal de trabaja
prop_emp <- prop.table(table(empleo$trabaja))
bp1 <- barplot(prop_emp,
        names.arg = c("No trabaja\n(y = 0)", "Trabaja\n(y = 1)"),
        col = gray(c(0.75, 0.30)), border = "white",
        ylim = c(0, 0.75), ylab = "Proporción",
        main = "Variable dependiente (binaria)")
abline(h=0)
text(bp1, as.numeric(prop_emp)+0.03,
     sprintf("%.1f%%", as.numeric(prop_emp)*100), font=2, cex=0.9)

# Panel 2: tasa de empleo por nivel educativo (agrupado)
empleo$educ_grupo <- cut(empleo$educacion, breaks=c(5,9,12,16,22),
                          labels=c("6-9","10-12","13-16","17+"))
tasa_educ <- tapply(empleo$trabaja, empleo$educ_grupo, mean, na.rm=TRUE)
bp2 <- barplot(tasa_educ,
        col = gray(seq(0.75, 0.25, length.out=4)),
        border = "white",
        ylim = c(0, 0.95),
        ylab = "Tasa de empleo",
        xlab = "Años de educación",
        main = "Empleo por nivel educativo")
abline(h=0)
text(bp2, tasa_educ+0.025, sprintf("%.1f%%",tasa_educ*100), font=2, cex=0.85)

par(mfrow=c(1,1))
Figure 1.9: Análisis de la variable dependiente binaria (trabaja). El panel izquierdo muestra la distribución marginal: el 58.2% de los individuos trabaja. El panel derecho muestra cómo la tasa de empleo varía con la educación, sugiriendo una relación positiva que los modelos Probit/Logit deberán cuantificar.

1.6.4 Análisis bivariante: relaciones entre variables

Con el EDA univariante resuelto, pasamos al análisis de relaciones. Para variables cuantitativas, el gráfico de dispersión (scatter plot) y la matriz de correlaciones son las herramientas básicas. Para la relación entre la variable dependiente binaria y una cuantitativa, la representación habitual es comparar las distribuciones de la covariable entre los dos grupos (\(y=0\) e \(y=1\)) mediante boxplots.

Code
par(mfrow=c(1,3), mar=c(4,4,2,0.5))

for (vvar in c("edad","educacion","experiencia")) {
  boxplot(empleo[[vvar]] ~ empleo$trabaja,
          col = gray(c(0.80, 0.40)),
          names = c("y = 0\n(no emp.)","y = 1\n(empleado)"),
          ylab = switch(vvar,
                        edad         = "Años",
                        educacion    = "Años",
                        experiencia  = "Años"),
          main = switch(vvar,
                        edad         = "Edad",
                        educacion    = "Educación",
                        experiencia  = "Experiencia"),
          xlab = "",
          border = gray(0.2))
}
par(mfrow=c(1,1))
Figure 1.10: Análisis bivariante del dataset de mercado laboral. Los boxplots comparan la distribución de cada covariable entre no empleados (y=0, gris claro) y empleados (y=1, gris oscuro). Las diferencias más llamativas aparecen en educación y experiencia, lo que anticipa que serán las variables con mayor poder explicativo en el modelo.

La Figure 1.10 muestra con claridad que los empleados tienen, en promedio, más educación y más experiencia que los no empleados. La diferencia en edad no es tan pronunciada, lo que sugiere que no es la edad per se sino la combinación de formación y experiencia lo que determina la empleabilidad. Estos patrones son exactamente los que el modelo Probit o Logit capturará de forma formal en el siguiente capítulo.

1.7 Casos prácticos

Los tres casos prácticos de este capítulo introductorio tienen un objetivo didáctico claro: entrenar el análisis exploratorio de datos con tres tipos diferentes de variable dependiente limitada. El alumno aprenderá a reconocer visualmente los patrones característicos de cada tipo de VDL antes de estudiar los modelos que las tratan. Cada caso tiene un script interactivo en R disponible en el repositorio del manual.

1.7.1 Caso práctico 1: Participación laboral — variable binaria

Contexto. Los datos del CP01 corresponden a 600 personas en edad activa (20-65 años) de una economía hipotética. La variable dependiente trabaja es binaria: vale 1 si la persona tiene empleo remunerado y 0 si está desempleada o inactiva. Las covariables recogen características demográficas y de capital humano: edad, educación (años de escolarización), experiencia laboral acumulada, sexo, número de hijos y, para los empleados, el salario bruto por hora y el sector de actividad.

Este caso reproduce exactamente el EDA mostrado en la Section 1.6. El alumno puede reproducir todos los análisis de forma interactiva ejecutando el siguiente script:

T01_CP01_mECO_EDA_Empleo.R

El patrón visual distintivo de una variable binaria es la Figure 1.9: en lugar de un histograma continuo, vemos dos barras que representan las proporciones de ceros y unos. La diferencia entre esas proporciones en distintos subgrupos — por educación, por sexo, por número de hijos — es la señal que el modelo Logit o Probit luego cuantificará.

1.7.2 Caso práctico 2: Gasto en seguros del hogar — variable censurada

Contexto. El dataset CP02 contiene información sobre 500 hogares. La variable dependiente gasto_seguros refleja el gasto mensual en seguros médicos privados. El 48% de los hogares no tiene ningún seguro privado (gasto = 0), mientras que el 52% restante presenta gastos que van desde cantidades modestas hasta valores elevados. Las covariables son: renta mensual del hogar, edad del cabeza de familia, número de miembros, nivel educativo del cabeza de familia, zona de residencia (urbana/rural) y si disponen de vehículo propio.

Code
load("data/T01_CP02_gasto_hogar.RData")

par(mfrow=c(1,2), mar=c(4.5,4.5,2,0.5))

# Panel 1: histograma con masa en 0
n_ceros_cp2 <- sum(hogar$gasto_seguros == 0)
hist(hogar$gasto_seguros, breaks=30, col=gray(0.70), border="white",
     main="Gasto en seguros",
     xlab="Gasto mensual (€)", ylab="Frecuencia")
rect(par("usr")[1], 0, 0.5, n_ceros_cp2, col=gray(0.30), border=NA)
text(1, n_ceros_cp2*0.6,
     sprintf("%d hogares\nsin seguro\n(%.0f%%)", n_ceros_cp2,
             100*n_ceros_cp2/nrow(hogar)),
     pos=4, cex=0.75, font=2)

# Panel 2: gasto vs renta
plot(hogar$renta, hogar$gasto_seguros,
     pch  = ifelse(hogar$gasto_seguros==0, 1, 16),
     col  = ifelse(hogar$gasto_seguros==0, gray(0.65), gray(0.25)),
     xlab = "Renta mensual (€ miles)", ylab="Gasto en seguros (€)",
     main = "Gasto vs Renta")
abline(h=0, lty=2, col=gray(0.5))
abline(lm(gasto_seguros ~ renta, data=hogar), lwd=2, lty=1, col="black")
legend("topleft", legend=c("Gasto > 0","Gasto = 0 (censurado)","MCO sesgado"),
       pch=c(16,1,NA), lty=c(NA,NA,1), lwd=c(NA,NA,2),
       col=c(gray(0.25),gray(0.65),"black"), bty="n", cex=0.75)

par(mfrow=c(1,1))
Figure 1.11: Distribución del gasto en seguros médicos (CP02). El panel izquierdo muestra la distribución completa con la masa discreta en cero (barra sombreada) y la distribución continua de los valores positivos. El panel derecho muestra la relación entre renta y gasto, evidenciando que los hogares con gasto cero (puntos huecos) están concentrados en los niveles bajos de renta.

La Figure 1.11 muestra con claridad la estructura típica de una variable censurada. El panel izquierdo revela la mezcla discreta-continua: una barra negra en cero (los 240 hogares sin gasto en seguros) seguida de una distribución continua a la derecha. Esta estructura es precisamente la que el modelo Tobit está diseñado para manejar. El panel derecho ilustra el problema de MCO: la recta estimada está sesgada hacia abajo porque trata los ceros como si fueran valores reales, cuando en realidad son el resultado de la censura. La pendiente verdadera es más pronunciada de lo que MCO sugiere.

Code
hogar$tiene_seguro <- ifelse(hogar$gasto_seguros > 0, "Con seguro", "Sin seguro")
vars_cp2 <- c("renta","edad_cabeza","num_miembros","educacion_cabeza")
labs_cp2 <- c("Renta (€ miles)","Edad cabeza fam.","Miembros hogar","Educ. cabeza (años)")

desc_cp2 <- do.call(rbind, lapply(seq_along(vars_cp2), function(i) {
  v <- vars_cp2[i]
  data.frame(
    Variable     = labs_cp2[i],
    `Sin seguro` = sprintf("%.1f (%.1f)",
                           mean(hogar[[v]][hogar$tiene_seguro=="Sin seguro"]),
                           sd(hogar[[v]][hogar$tiene_seguro=="Sin seguro"])),
    `Con seguro` = sprintf("%.1f (%.1f)",
                           mean(hogar[[v]][hogar$tiene_seguro=="Con seguro"]),
                           sd(hogar[[v]][hogar$tiene_seguro=="Con seguro"])),
    check.names=FALSE
  )
}))
kbl(desc_cp2, booktabs=TRUE, row.names=FALSE,
    col.names=c("Variable","Sin seguro (media ± DT)","Con seguro (media ± DT)")) |>
  kable_styling(latex_options=c("hold_position","scale_down"),
                bootstrap_options=c("condensed","striped"), full_width=FALSE)
Table 1.4: Estadísticos descriptivos del dataset de gasto en seguros del hogar (CP02), comparando hogares con y sin gasto en seguros. La renta media de los hogares con seguro casi dobla a la de los hogares sin seguro, lo que confirma la importancia de esta variable en la decisión de asegurarse.
Variable Sin seguro (media ± DT) Con seguro (media ± DT)
Renta (€ miles) 22.5 (11.3) 62.6 (27.3)
Edad cabeza fam. 48.9 (14.4) 50.9 (15.0)
Miembros hogar 2.5 (1.5) 2.7 (1.5)
Educ. cabeza (años) 11.7 (2.9) 12.3 (2.8)

El alumno puede reproducir y ampliar este análisis con el siguiente script:

T01_CP02_mECO_EDA_Gasto.R

1.7.3 Caso práctico 3: Visitas al médico — variable de recuento

Contexto. El dataset CP03 recoge información sobre 600 individuos. La variable dependiente visitas es el número de visitas al médico durante el último año. Se trata de una variable de recuento: solo puede tomar valores enteros no negativos \(\{0, 1, 2, \ldots\}\). Las covariables son: edad, presencia de enfermedad crónica, nivel de ingresos, tenencia de seguro privado, educación, sexo y existencia de limitación funcional.

Code
load("data/T01_CP03_visitas_medico.RData")

par(mfrow=c(1,2), mar=c(4.5,4.5,2,0.5))

# Panel 1: distribución de recuentos
tab_vis <- table(factor(pmin(medico$visitas, 20), levels=0:20))
bp3 <- barplot(tab_vis, col=gray(0.65), border="white",
        main="Distribución de visitas",
        xlab="Número de visitas (máx. 20+)", ylab="Frecuencia",
        names.arg=c("0",rep("",4),"5",rep("",4),"10",rep("",4),"15",rep("",4),"20+"))
abline(h=0)
mu_v  <- mean(medico$visitas)
var_v <- var(medico$visitas)
legend("topright",
       legend = c(sprintf("Media = %.1f", mu_v),
                  sprintf("Varianza = %.1f", var_v),
                  sprintf("Var/Media = %.1f", var_v/mu_v)),
       bty = "n", cex = 0.78)

# Panel 2: boxplot por cronicidad
boxplot(visitas ~ cronico, data=medico,
        names=c("Sin crónico\n(cronico=0)","Con crónico\n(cronico=1)"),
        col=gray(c(0.80,0.40)), border=gray(0.2),
        main="Visitas por cronicidad",
        ylab="Número de visitas")

par(mfrow=c(1,1))
Figure 1.12: Distribución del número de visitas al médico (CP03). El panel izquierdo muestra la distribución de recuentos: asimétrica a la derecha y concentrada en valores bajos, con una cola larga. El panel derecho compara las distribuciones entre pacientes con y sin enfermedad crónica — el diagnóstico de cronicidad más que duplica el número de visitas. La sobredispersión (varianza/media = 10.3) indica que el modelo de Poisson simple será insuficiente.

La Figure 1.12 pone de manifiesto dos características fundamentales de los datos de recuento. La primera es la asimetría positiva de la distribución: la mayoría de los individuos realizan pocas visitas, pero algunos hacen muchas, generando una cola derecha larga. Esta asimetría hace que la distribución Normal sea completamente inapropiada para modelar este tipo de variable. La segunda característica es la sobredispersión: la varianza (81.0) supera enormemente a la media (7.8), con un ratio de 10.3. Esto viola el supuesto de equidispersión del modelo de Poisson (\(\text{Var}(y) = E(y)\)) y anticipa que el modelo Binomial Negativa, que permite sobredispersión, será más adecuado. Estos conceptos se desarrollan en detalle en el el Capítulo 4.

El alumno puede explorar interactivamente estos datos con el siguiente script:

T01_CP03_mECO_EDA_Visitas.R

1.8 Guía de comandos R para este capítulo

1.8.1 load() — Carga de datos en formato RData

Los datasets del manual se distribuyen en formato .RData, el formato nativo de R para almacenar uno o varios objetos simultáneamente. La función load() lee ese fichero y deposita los objetos directamente en el entorno de trabajo, listos para usar con su nombre original.

load("data/T01_CP01_empleo_basico.RData")

El único parámetro obligatorio es la ruta al fichero. Después de ejecutar load(), los objetos del fichero aparecen en el panel Environment de RStudio. No hace falta asignar el resultado a ninguna variable.

1.8.2 str() — Estructura interna del objeto

Antes de tocar un dato, hay que saber con qué tipo de objeto se está trabajando. str() muestra de forma compacta el tipo de cada columna, el número de observaciones, los primeros valores y la clase del objeto. Es el primer comando que debe ejecutarse siempre tras cargar un dataset.

str(empleo)

No tiene parámetros opcionales relevantes para el uso habitual. La salida indica, para cada columna, si es numérica (num), entera (int), factor (Factor) o carácter (chr), lo cual determina qué análisis estadístico es apropiado.

1.8.3 table() y prop.table() — Frecuencias y proporciones

Para variables categóricas o binarias, table() cuenta cuántas observaciones toman cada valor posible. prop.table(), aplicado sobre el resultado de table(), convierte las frecuencias absolutas en proporciones.

table(empleo$trabaja)
prop.table(table(empleo$trabaja))

table() acepta una o dos variables: con una variable produce una tabla unidimensional de frecuencias; con dos variables genera una tabla de contingencia cruzada. prop.table() acepta el argumento margin=1 (proporciones por filas) o margin=2 (por columnas) para tablas bidimensionales.

1.8.4 hist() — Histograma de distribución

hist() visualiza la distribución de una variable continua dividiendo su rango en intervalos (bins) y contando cuántas observaciones caen en cada uno. Es la herramienta más inmediata para detectar asimetría, valores atípicos y la forma general de la distribución.

hist(empleo$edad, breaks = 15, col = gray(0.75), border = "white",
     xlab = "Edad (años)", ylab = "Frecuencia",
     main = "Distribución de la edad")

Los parámetros principales son: breaks controla el número de intervalos (más breaks = más detalle); col fija el color de las barras (usamos gray(0.75) para impresión en B&N); border controla el color del borde de cada barra; xlab, ylab y main son las etiquetas de los ejes y el título.

1.8.5 boxplot() — Diagrama de caja por grupos

El diagrama de caja-y-bigotes resume de forma compacta la distribución de una variable: mediana, rango intercuartílico (IQR = Q3 − Q1), bigotes hasta 1.5×IQR y puntos individuales más allá de los bigotes. Cuando se usa con la fórmula y ~ grupo, compara la distribución entre grupos y permite detectar si hay diferencias relevantes entre ellos.

boxplot(edad ~ trabaja, data = empleo,
        names = c("No empleado", "Empleado"),
        col = gray(c(0.80, 0.45)), border = gray(0.2),
        ylab = "Edad (años)", xlab = "")

La fórmula y ~ grupo indica que y es la variable a representar y grupo la variable que define las categorías. col asigna un color a cada caja; border controla el color del contorno; names permite renombrar las categorías del eje horizontal.

1.8.6 mean(y == 0) — Proporción de ceros (diagnóstico de censura)

Para detectar si una variable continua está censurada en cero, el diagnóstico más directo es calcular qué proporción de observaciones presenta exactamente el valor cero. mean(y == 0) funciona porque en R y == 0 produce un vector lógico (TRUE/FALSE) y mean() trata TRUE como 1 y FALSE como 0.

mean(seguros$gasto_seguros == 0)

Un resultado superior al 15-20% indica censura sustancial y justifica el uso del modelo Tobit en lugar de MCO.

1.8.7 var(y) / mean(y) — Ratio de sobredispersión (diagnóstico para recuentos)

Para datos de recuento, el primer diagnóstico que hay que hacer es comparar varianza y media. Bajo el modelo de Poisson, ambas deben ser iguales (VMR = 1). Un ratio Var/Media significativamente superior a 1 indica sobredispersión y hace necesario el modelo Binomial Negativa.

var(medico$visitas) / mean(medico$visitas)

No hay parámetros adicionales. Como regla práctica, un VMR > 2 indica sobredispersión notable; un VMR > 5 indica sobredispersión severa que el modelo de Poisson no puede absorber.

Los scripts de este capítulo están disponibles en la carpeta scripts/ del repositorio del manual, en:

github.com/carlanta/MicroEconometrics

Cada script reproduce todos los análisis de forma interactiva y con pausas entre secciones.