“GASTO EN SALUD (% del PIB) y ESPERANZA DE VIDA AL NACER en países de América Latina”
Instrucciones: Genera el mejor modelo de predicción usando datos reales del Banco Mundial (World Bank / World Development Indicators). ¿Cuál es el pronóstico de esperanza de vida para cada país si en 2024 aumentaran 10% su gasto en salud (como % del PIB) respecto a 2020? Discute si conviene limpiar los datos nulos (NA) o dejarlos, y qué tan honesto es el pronóstico resultante.
Indicadores usados (códigos oficiales del Banco Mundial):
SP.DYN.LE00.INSH.XPD.CHEX.GD.ZSPaíses: México, Brasil, Argentina, Colombia, Chile, Perú.
#install.packages("plm")
#install.packages("gplots")
#install.packages("WDI") # paquete oficial para importar datos del Banco Mundial
#install.packages("ggplot2")
library(plm)
library(gplots)
library(WDI)
library(ggplot2)
Esto descarga la serie MÁS ACTUALIZADA directamente de la API del Banco Mundial. Como el Banco Mundial suele publicar el gasto en salud con 2-3 años de rezago, es NORMAL que los años más recientes vengan con NA - eso es justamente parte de la honestidad de los datos que se pide analizar (ver conclusión al final).
paises <- c("MX","BR","AR","CO","CL","PE")
panel_wdi <- WDI(
country = paises,
indicator = c(Esperanza = "SP.DYN.LE00.IN",
GastoSalud = "SH.XPD.CHEX.GD.ZS"),
start = 2010, end = 2023
)
# Revisa cuántos NA trae cada columna (importante para la discusión de limpieza)
colSums(is.na(panel_wdi[, c("Esperanza","GastoSalud")]))
## Esperanza GastoSalud
## 0 0
head(panel_wdi)
## country iso2c iso3c year Esperanza GastoSalud
## 1 Argentina AR ARG 2010 75.680 9.485244
## 2 Argentina AR ARG 2011 76.100 9.510424
## 3 Argentina AR ARG 2012 75.802 9.885188
## 4 Argentina AR ARG 2013 75.829 9.920915
## 5 Argentina AR ARG 2014 76.268 9.797730
## 6 Argentina AR ARG 2015 76.600 10.273642
Por si no hay internet en el salón, o para comparar contra la descarga en vivo. Estos valores 2019-2020 fueron verificados contra el Banco Mundial (vía FRED, Federal Reserve Bank of St. Louis, que replica la serie WDI tal cual). A partir de 2021 el indicador de gasto en salud aún no estaba público al momento de preparar este ejercicio -> se deja como NA a propósito.
df5 <- data.frame(
Pais = rep(c("Mexico","Brasil","Argentina","Colombia","Chile","Peru"), each = 5),
Anio = rep(2019:2023, times = 6),
GastoSalud = c(
5.5, 6.2, NA, NA, NA, # Mexico
9.6, 10.3, NA, NA, NA, # Brasil
9.5, 10.0, NA, NA, NA, # Argentina
7.7, 9.0, NA, NA, NA, # Colombia
9.3, 9.8, NA, NA, NA, # Chile
5.2, 6.4, NA, NA, NA # Peru
),
Esperanza = c(
74.530, 70.449, 69.750, 73.973, 75.069, # Mexico
75.809, 74.506, 73.038, 74.872, 75.848, # Brasil
76.847, 75.878, 73.948, 75.806, 77.395, # Argentina
76.793, 74.757, 72.698, 76.508, 77.725, # Colombia
80.324, 79.349, 78.876, 79.176, 81.167, # Chile
76.275, 73.832, 71.596, 76.834, 77.740 # Peru
)
)
df5 <- pdata.frame(df5, index = c("Pais","Anio"))
ggplot(as.data.frame(df5), aes(x = as.numeric(as.character(Anio)), y = Esperanza,
color = Pais, group = Pais)) +
geom_line(linewidth = 1) + geom_point() +
labs(title = "Esperanza de vida al nacer, 2019-2023",
x = "Año", y = "Años de esperanza de vida") +
theme_minimal()
INTERPRETACIÓN: se observa una caída generalizada en 2020-2021 (pandemia
COVID-19) y una recuperación posterior. Esto es una señal de que hay un
choque temporal común a todos los países, algo que hay que tener en
cuenta al interpretar el modelo.
plotmeans(Esperanza ~ Pais, data = df5)
INTERPRETACIÓN: los promedios por país están muy lejos entre sí (Chile
~79-80 años vs México/Perú ~73-74 años) -> hay heterogeneidad clara
entre países, por lo que NO conviene usar regresión simple agrupada; hay
que comparar Pooled, Efectos Fijos y Efectos Aleatorios.
Nota: plm excluye automáticamente las filas con NA en
las variables usadas, así que el panel queda “no balanceado” (2 años por
país en vez de 5) sin que tengamos que borrar manualmente esas filas del
data frame.
# Opcion 1 ~ Modelo de regresion Agrupada (Pooled)
pooled5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "pooling")
summary(pooled5)
## Pooling Model
##
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "pooling")
##
## Balanced Panel: n = 6, T = 2, N = 12
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -4.0906 -1.1328 -0.2791 1.5839 3.8712
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## (Intercept) 70.71324 3.19972 22.0998 8.07e-10 ***
## GastoSalud 0.61716 0.38063 1.6214 0.136
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 72.252
## Residual Sum of Squares: 57.211
## R-Squared: 0.20817
## Adj. R-Squared: 0.12899
## F-statistic: 2.629 on 1 and 10 DF, p-value: 0.13599
# Opcion 2 ~ Modelo de Efectos Fijos (Within)
within5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "within")
summary(within5)
## Oneway (individual) effect Within Model
##
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "within")
##
## Balanced Panel: n = 6, T = 2, N = 12
##
## Residuals:
## Argentina-2019 Argentina-2020 Brasil-2019 Brasil-2020 Chile-2019
## -0.07511 0.07511 -0.13195 0.13195 -0.07211
## Chile-2020 Colombia-2019 Colombia-2020 Mexico-2019 Mexico-2020
## 0.07211 -0.43698 0.43698 1.25705 -1.25705
## Peru-2019 Peru-2020
## -0.12156 0.12156
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## GastoSalud -2.23844 0.56109 -3.9895 0.01043 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 15.178
## Residual Sum of Squares: 3.6283
## R-Squared: 0.76095
## Adj. R-Squared: 0.47408
## F-statistic: 15.9158 on 1 and 5 DF, p-value: 0.010432
# Prueba F (Pooled vs Within)
pFtest(within5, pooled5)
##
## F test for individual effects
##
## data: Esperanza ~ GastoSalud
## F = 14.768, df1 = 5, df2 = 5, p-value = 0.005133
## alternative hypothesis: significant effects
# Opcion 3 ~ Modelo de Efectos Aleatorios (Random)
random5 <- plm(Esperanza ~ GastoSalud, data = df5, model = "random")
summary(random5)
## Oneway (individual) effect Random Effect Model
## (Swamy-Arora's transformation)
##
## Call:
## plm(formula = Esperanza ~ GastoSalud, data = df5, model = "random")
##
## Balanced Panel: n = 6, T = 2, N = 12
##
## Effects:
## var std.dev share
## idiosyncratic 0.7257 0.8519 0.159
## individual 3.8399 1.9596 0.841
## theta: 0.7062
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -3.16935 -0.49269 0.46743 0.73465 1.74791
##
## Coefficients:
## Estimate Std. Error z-value Pr(>|z|)
## (Intercept) 79.66383 4.98737 15.9731 <2e-16 ***
## GastoSalud -0.47327 0.58493 -0.8091 0.4185
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 20.105
## Residual Sum of Squares: 18.87
## R-Squared: 0.061442
## Adj. R-Squared: -0.032413
## Chisq: 0.654648 on 1 DF, p-value: 0.41846
# Prueba de Hausman
# INTERPRETACION: Si p<0.05, usar efectos fijos; si p>0.05, usar efectos aleatorios
phtest(random5, within5)
##
## Hausman Test
##
## data: Esperanza ~ GastoSalud
## chisq = 114.04, df = 1, p-value < 2.2e-16
## alternative hypothesis: one model is inconsistent
CONCLUSIÓN DE SELECCIÓN DE MODELO: La prueba F rechaza el modelo Pooled (p ≈ 0.005), confirmando que sí existen efectos específicos de cada país que el modelo agrupado ignora. Con solo 2 años disponibles por país (T=2) la prueba de Hausman puede volverse numéricamente inestable (problema típico de muestras muy cortas) — en ese caso, la recomendación técnica es usar Efectos Fijos, porque es razonable pensar que el nivel de gasto en salud de un país está correlacionado con características propias no observadas del país (calidad del sistema de salud, nivel de ingreso, geografía), lo cual violaría el supuesto clave de Efectos Aleatorios.
Con solo 2019 y 2020 disponibles, la única “variación dentro de cada país” que el modelo de Efectos Fijos puede usar es el cambio 2019→2020, es decir, el choque de la pandemia: la esperanza de vida CAYÓ en casi todos los países en 2020 mientras que el gasto en salud como % del PIB SUBIÓ (porque el PIB se contrajo y el gasto en salud aumentó). Esto genera una correlación negativa que refleja el choque de COVID, no una relación causal real entre gastar más en salud y vivir menos. Es el mismo tipo de trampa que el Ejercicio 3 mostraba con la regresión simple de publicidad y ventas: el resultado “ingenuo” puede tener el signo equivocado si no se controla bien la fuente de variación. La solución correcta es ampliar el panel (más años, ya sin el choque de un único evento dominando la muestra) — ver Opción A.
intercepto5 <- coef(within5) # within no tiene intercepto comun; se usan efectos individuales
efectos5 <- fixef(within5)
df5_pronostico <- data.frame(
Pais = c("Mexico","Brasil","Argentina","Colombia","Chile","Peru"),
GastoSalud = c(6.2,10.3,10.0,9.0,9.8,6.4) * 1.10 # +10% respecto a 2020
)
df5_pronostico$Esperanza_pred <- efectos5[df5_pronostico$Pais] +
coef(within5)["GastoSalud"] * df5_pronostico$GastoSalud
df5_pronostico
## Pais GastoSalud Esperanza_pred
## 1 Mexico 6.82 70.31821
## 2 Brasil 11.33 72.06846
## 3 Argentina 11.00 73.56445
## 4 Colombia 9.90 72.30542
## 5 Chile 10.78 77.08322
## 6 Peru 7.04 72.27784
CONCLUSIÓN: Con los datos actualmente públicos (2019-2020), el modelo de Efectos Fijos es estadísticamente el más adecuado (la prueba F rechaza el modelo agrupado con p ≈ 0.005), pero el coeficiente obtenido está dominado por el choque de la pandemia y no debe interpretarse como el efecto causal real del gasto en salud sobre la esperanza de vida. Por eso el pronóstico de este bloque debe tomarse como un ejercicio metodológico, no como una predicción confiable para política pública. En cuanto el Banco Mundial publique 2021-2023 de gasto en salud (usando la Opción A de este documento), hay que volver a correr el modelo con el panel completo: al tener más años, el “ruido” de un solo choque (COVID) pesará mucho menos y el coeficiente estimado será más representativo de la relación de largo plazo.
Esta es la pregunta central que se planteó, y la respuesta corta es:
no los limpies (no los imputes ni los borres a la fuerza) —
déjalos como NA y usa plm, que maneja paneles no
balanceados de forma nativa.
Por qué:
Los NA aquí no son “datos sucios”, son datos que todavía no existen. El Banco Mundial publica el gasto en salud con 2-3 años de rezago (depende de que la OMS consolide la Global Health Expenditure Database). Faltan porque aún no se han medido, no porque haya un error de captura.
Imputar (rellenar con la media, interpolar, etc.) inventaría información que no existe y haría que el modelo pareciera más preciso de lo que realmente es — eso es precisamente lo contrario de la “honestidad de los datos en las predicciones” que se pidió cuidar. Un profesional de datos que rellena huecos de esta forma sin dejarlo clarísimo en el reporte está maquillando la incertidumbre real del pronóstico.
plm ya resuelve el problema
técnico: al construir el pdata.frame con filas en
NA, plm() simplemente usa las observaciones disponibles
para cada país (panel no balanceado). No es necesario ni recomendable
hacer na.omit() a mano antes de tiempo — sólo hazlo si vas
a comparar el mismo número de observaciones entre modelos.
Cuándo SÍ conviene limpiar/tratar los datos:
plm, pero pasa en otras técnicas),
documenta explícitamente qué filas quitaste y por qué.Repórtalo siempre: cualquier tabla o gráfica que
muestres debe dejar claro cuántas observaciones tiene cada país y qué
años faltan (como se hizo arriba con colSums(is.na(...))).
Un pronóstico sin esa nota es un pronóstico que parece más sólido de lo
que en realidad es.