library(WDI)
library(dplyr)
library(tidyr)
library(ggplot2)
library(knitr)
library(kableExtra)
library(lmtest)
library(car)La esperanza de vida al nacer es uno de los indicadores más comprehensivos del bienestar de una población. Es decir, refleja de forma sintética las condiciones sanitarias, económicas y sociales que enfrentan los habitantes de un país a lo largo de su vida. Así mismo, en 2022 las diferencias entre países eran aún profundas: mientras algunos superaban los 85 años, otros no alcanzaban los 60. No obstante, estas cifras no son fortuitas; sin embargo, nos dicen que factores estructurales de diversa naturaleza determinan de manera significativa la longevidad de las personas.
Con el desarrollo de este taller, buscamos responder la siguiente pregunta: ¿Qué factores socioeconómicos y de salud explican las diferencias en esperanza de vida entre países en el año 2022? Es decir, se pretende identificar las causas subyacentes a las brechas de longevidad global. Para ello, se construye un modelo de regresión lineal múltiple utilizando datos del Banco Mundial con cinco variables independientes cuantitativas; asimismo, se incluye el grupo de ingreso del país como variable cualitativa. No obstante, la complejidad del fenómeno nos dice que un análisis meramente descriptivo sería insuficiente; sin embargo, a través de este diseño econométrico, es posible aislar el peso específico de cada factor en el bienestar poblacional.
Los datos provienen de los World Development Indicators (WDI) del
Banco Mundial, descargados mediante el paquete WDI de R. Se
seleccionó el año 2022 para obtener un corte transversal a nivel de
países. Tras eliminar agregados regionales y observaciones con valores
faltantes, la muestra final quedó compuesta por 165 países.
variables <- data.frame(
Rol = c(
"Dependiente",
"Independiente cuantitativa",
"Independiente cuantitativa",
"Independiente cuantitativa",
"Independiente cuantitativa",
"Independiente cuantitativa",
"Independiente cualitativa"
),
Variable = c(
"Esperanza de vida al nacer (años)",
"PIB per cápita (USD corrientes)",
"Gasto en salud (% del PIB)",
"Mortalidad infantil (por 1.000 nacidos vivos)",
"Acceso a agua potable (% de la población)",
"Tasa de desempleo (%)",
"Grupo de ingreso del país"
),
Codigo_WDI = c(
"SP.DYN.LE00.IN",
"NY.GDP.PCAP.CD",
"SH.XPD.CHEX.GD.ZS",
"SP.DYN.IMRT.IN",
"SH.H2O.BASW.ZS",
"SL.UEM.TOTL.ZS",
"income (WDI extra)"
),
stringsAsFactors = FALSE
)
kable(variables,
col.names = c("Rol", "Variable", "Codigo WDI"),
caption = "Tabla 1. Variables del modelo") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
column_spec(1, bold = TRUE)| Rol | Variable | Codigo WDI |
|---|---|---|
| Dependiente | Esperanza de vida al nacer (años) | SP.DYN.LE00.IN |
| Independiente cuantitativa | PIB per cápita (USD corrientes) | NY.GDP.PCAP.CD |
| Independiente cuantitativa | Gasto en salud (% del PIB) | SH.XPD.CHEX.GD.ZS |
| Independiente cuantitativa | Mortalidad infantil (por 1.000 nacidos vivos) | SP.DYN.IMRT.IN |
| Independiente cuantitativa | Acceso a agua potable (% de la población) | SH.H2O.BASW.ZS |
| Independiente cuantitativa | Tasa de desempleo (%) | SL.UEM.TOTL.ZS |
| Independiente cualitativa | Grupo de ingreso del país | income (WDI extra) |
La variable cualitativa income clasifica a los países en
cuatro categorías: Low income, Lower middle income, Upper middle income
y High income. La categoría de referencia en el modelo es Low
income.
datos_raw <- WDI(
country = "all",
indicator = c(
esperanza_vida = "SP.DYN.LE00.IN",
pib_per_capita = "NY.GDP.PCAP.CD",
gasto_salud = "SH.XPD.CHEX.GD.ZS",
mortalidad_inf = "SP.DYN.IMRT.IN",
agua_potable = "SH.H2O.BASW.ZS",
desempleo = "SL.UEM.TOTL.ZS"
),
start = 2022,
end = 2022,
extra = TRUE
)
datos <- datos_raw %>%
filter(region != "Aggregates") %>%
dplyr::select(country, iso2c, income,
esperanza_vida, pib_per_capita, gasto_salud,
mortalidad_inf, agua_potable, desempleo)
datos_modelo <- datos %>%
dplyr::select(-country, -iso2c) %>%
filter(income %in% c("Low income", "Lower middle income",
"Upper middle income", "High income")) %>%
na.omit() %>%
mutate(income = factor(income,
levels = c("Low income",
"Lower middle income",
"Upper middle income",
"High income")))
cat("Observaciones en el modelo:", nrow(datos_modelo))## Observaciones en el modelo: 165
etiquetas <- c(
esperanza_vida = "Esperanza de vida (anos)",
pib_per_capita = "PIB per capita (USD)",
gasto_salud = "Gasto en salud (% PIB)",
mortalidad_inf = "Mortalidad infantil (x1.000)",
agua_potable = "Acceso a agua potable (%)",
desempleo = "Tasa de desempleo (%)"
)
desc <- datos_modelo %>%
dplyr::select(-income) %>%
pivot_longer(everything(), names_to = "Variable", values_to = "Valor") %>%
group_by(Variable) %>%
summarise(
N = n(),
Media = round(mean(Valor, na.rm = TRUE), 2),
Mediana = round(median(Valor, na.rm = TRUE), 2),
DE = round(sd(Valor, na.rm = TRUE), 2),
Min = round(min(Valor, na.rm = TRUE), 2),
Max = round(max(Valor, na.rm = TRUE), 2)
) %>%
mutate(Variable = etiquetas[Variable])
kable(desc,
col.names = c("Variable", "N", "Media", "Mediana", "D.E.", "Min", "Max"),
caption = "Tabla 2. Estadisticas descriptivas") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Variable | N | Media | Mediana | D.E. | Min | Max |
|---|---|---|---|---|---|---|
| Acceso a agua potable (%) | 165 | 89.30 | 95.94 | 14.55 | 35.13 | 100.00 |
| Tasa de desempleo (%) | 165 | 6.94 | 5.05 | 5.83 | 0.13 | 36.47 |
| Esperanza de vida (anos) | 165 | 72.55 | 73.51 | 8.08 | 18.82 | 84.00 |
| Gasto en salud (% PIB) | 165 | 6.64 | 6.53 | 3.04 | 1.77 | 23.09 |
| Mortalidad infantil (x1.000) | 165 | 19.78 | 13.10 | 21.36 | 1.70 | 189.10 |
| PIB per capita (USD) | 165 | 16880.66 | 6515.59 | 23928.87 | 302.99 | 123719.66 |
colores <- c(
"Low income" = "#e74c3c",
"Lower middle income" = "#e67e22",
"Upper middle income" = "#3498db",
"High income" = "#2ecc71"
)
datos_modelo %>%
count(income) %>%
ggplot(aes(x = income, y = n, fill = income)) +
geom_col(width = 0.6, show.legend = FALSE) +
geom_text(aes(label = n), vjust = -0.5, size = 4, fontface = "bold") +
scale_fill_manual(values = colores) +
labs(title = "Paises por grupo de ingreso (2022)",
x = "Grupo de ingreso", y = "Numero de paises") +
theme_minimal(base_size = 13) +
theme(axis.text.x = element_text(angle = 15, hjust = 1))La distribución de países por grupo de ingreso muestra una composición relativamente balanceada de la muestra, con una mayor concentración en países de ingresos altos (53) y medios (47 y 44), y una menor representación de países de bajos ingresos.
Esta distribución es relevante porque garantiza variabilidad en la
variable cualitativa income, lo que permite capturar
diferencias estructurales entre niveles de desarrollo. Sin embargo, la
menor cantidad de países de bajos ingresos podría influir en la
precisión de las estimaciones para este grupo.
ggplot(datos_modelo, aes(x = income, y = esperanza_vida, fill = income)) +
geom_boxplot(alpha = 0.8, show.legend = FALSE, outlier.shape = 21) +
scale_fill_manual(values = colores) +
labs(title = "Esperanza de vida por grupo de ingreso (2022)",
x = "Grupo de ingreso", y = "Esperanza de vida (anos)") +
theme_minimal(base_size = 13) +
theme(axis.text.x = element_text(angle = 15, hjust = 1))El diagrama de cajas evidencia una clara relación positiva entre el nivel de ingreso y la esperanza de vida. A medida que aumenta el nivel de ingreso del país, la mediana de la esperanza de vida también se incrementa de forma sistemática.
Los países de bajos ingresos presentan no solo menores niveles de esperanza de vida, sino también mayor dispersión, lo que indica heterogeneidad en sus condiciones sanitarias y sociales. En contraste, los países de altos ingresos muestran valores más elevados y concentrados, reflejando sistemas de salud más robustos y condiciones de vida más homogéneas.
ggplot(datos_modelo, aes(x = mortalidad_inf, y = esperanza_vida, color = income)) +
geom_point(alpha = 0.7, size = 2.5) +
geom_smooth(method = "lm", se = FALSE, color = "black",
linewidth = 0.8, linetype = "dashed") +
scale_color_manual(values = colores) +
labs(title = "Mortalidad infantil vs. Esperanza de vida (2022)",
x = "Mortalidad infantil (por 1.000 nacidos vivos)",
y = "Esperanza de vida (anos)",
color = "Grupo de ingreso") +
theme_minimal(base_size = 13)El gráfico de dispersión muestra una relación negativa fuerte y claramente no lineal entre la mortalidad infantil y la esperanza de vida. A medida que aumenta la mortalidad infantil, la esperanza de vida disminuye de forma pronunciada. La línea de tendencia confirma esta relación inversa, evidenciando que la mortalidad infantil es uno de los principales determinantes de la longevidad.
ggplot(datos_modelo, aes(x = pib_per_capita, y = esperanza_vida, color = income)) +
geom_point(alpha = 0.7, size = 2.5) +
geom_smooth(method = "lm", se = FALSE, color = "black",
linewidth = 0.8, linetype = "dashed") +
scale_x_log10(labels = scales::comma) +
scale_color_manual(values = colores) +
labs(title = "PIB per capita vs. Esperanza de vida (2022)",
x = "PIB per capita (USD, escala logaritmica)",
y = "Esperanza de vida (anos)",
color = "Grupo de ingreso") +
theme_minimal(base_size = 13)El gráfico evidencia una relación positiva entre el PIB per cápita y la esperanza de vida, aunque con rendimientos decrecientes. En niveles bajos de ingreso, pequeños aumentos en el PIB generan mejoras importantes en la esperanza de vida. Sin embargo, a medida que el ingreso aumenta, el efecto marginal disminuye, lo cual se observa en la forma curvada de la relación.
modelo <- lm(esperanza_vida ~ pib_per_capita + gasto_salud +
mortalidad_inf + agua_potable + desempleo + income,
data = datos_modelo)
summary(modelo)##
## Call:
## lm(formula = esperanza_vida ~ pib_per_capita + gasto_salud +
## mortalidad_inf + agua_potable + desempleo + income, data = datos_modelo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5.2827 -1.4041 -0.0475 1.6567 5.2292
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.937e+01 1.994e+00 34.784 < 2e-16 ***
## pib_per_capita 6.035e-05 1.184e-05 5.097 9.85e-07 ***
## gasto_salud 4.769e-02 6.614e-02 0.721 0.472009
## mortalidad_inf -2.826e-01 1.361e-02 -20.765 < 2e-16 ***
## agua_potable 9.306e-02 2.433e-02 3.825 0.000189 ***
## desempleo 2.192e-02 3.305e-02 0.663 0.508096
## incomeLower middle income -1.095e+00 7.725e-01 -1.417 0.158370
## incomeUpper middle income -1.689e+00 9.385e-01 -1.800 0.073764 .
## incomeHigh income -8.181e-01 1.079e+00 -0.758 0.449528
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 2.288 on 156 degrees of freedom
## Multiple R-squared: 0.9238, Adjusted R-squared: 0.9199
## F-statistic: 236.3 on 8 and 156 DF, p-value: < 2.2e-16
Bondad de ajuste: El modelo presenta un R² de 0.9238 y un R² ajustado de 0.9199, lo que significa que explica más del 92% de la variabilidad en la esperanza de vida. Esto indica un ajuste muy sólido y confiable.
Intercepto: El valor del intercepto (≈ 69.37) representa la esperanza de vida promedio cuando todas las variables independientes están en cero. Aunque no tiene interpretación práctica directa, sirve como punto de referencia en el modelo.
Variables significativas:
Variables no significativas:
income) tampoco resultan
significativas, aunque la categoría Upper middle income se acerca al
nivel de significancia (p ≈ 0.07).nombres <- c(
"(Intercept)" = "Intercepto",
"pib_per_capita" = "PIB per capita",
"gasto_salud" = "Gasto en salud (% PIB)",
"mortalidad_inf" = "Mortalidad infantil",
"agua_potable" = "Acceso a agua potable",
"desempleo" = "Tasa de desempleo",
"incomeLower middle income" = "D: Lower middle income",
"incomeUpper middle income" = "D: Upper middle income",
"incomeHigh income" = "D: High income"
)
coefs <- as.data.frame(summary(modelo)$coefficients)
coefs$Variable <- nombres[rownames(coefs)]
coefs <- coefs %>%
mutate(
Sig = case_when(
`Pr(>|t|)` < 0.001 ~ "***",
`Pr(>|t|)` < 0.01 ~ "**",
`Pr(>|t|)` < 0.05 ~ "*",
`Pr(>|t|)` < 0.1 ~ ".",
TRUE ~ ""
),
Estimate = round(Estimate, 6),
`Std. Error` = round(`Std. Error`, 6),
`t value` = round(`t value`, 3),
`Pr(>|t|)` = formatC(`Pr(>|t|)`, format = "e", digits = 3)
) %>%
dplyr::select(Variable, Estimate, `Std. Error`, `t value`, `Pr(>|t|)`, Sig)
kable(coefs,
col.names = c("Variable", "Estimado", "Error Std.", "t", "Valor p", "Sig."),
caption = "Tabla 3. Coeficientes del modelo") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
row_spec(which(coefs$Sig == "***"), bold = TRUE,
color = "#155724", background = "#d4edda")| Variable | Estimado | Error Std. | t | Valor p | Sig. | |
|---|---|---|---|---|---|---|
| (Intercept) | Intercepto | 69.370425 | 1.994306 | 34.784 | 2.141e-75 | *** |
| pib_per_capita | PIB per capita | 0.000060 | 0.000012 | 5.097 | 9.847e-07 | *** |
| gasto_salud | Gasto en salud (% PIB) | 0.047688 | 0.066145 | 0.721 | 4.720e-01 | |
| mortalidad_inf | Mortalidad infantil | -0.282593 | 0.013609 | -20.765 | 9.351e-47 | *** |
| agua_potable | Acceso a agua potable | 0.093055 | 0.024330 | 3.825 | 1.889e-04 | *** |
| desempleo | Tasa de desempleo | 0.021922 | 0.033048 | 0.663 | 5.081e-01 | |
| incomeLower middle income | D: Lower middle income | -1.094953 | 0.772527 | -1.417 | 1.584e-01 | |
| incomeUpper middle income | D: Upper middle income | -1.689410 | 0.938464 | -1.800 | 7.376e-02 | . |
| incomeHigh income | D: High income | -0.818077 | 1.079100 | -0.758 | 4.495e-01 |
Significancia: *** p<0.001 – **
p<0.01 – * p<0.05 – . p<0.1
El modelo presenta un R^2 = 0.9238 y un R^2 ajustado = 0.9199, lo que indica que el 92% de la variabilidad en la esperanza de vida entre países queda explicada por las variables del modelo. La prueba F global es altamente significativa (F = 236.3, p < 2.2e-16).
Mortalidad infantil (b = -0.283, p < 0.001): es el predictor más potente. Por cada aumento de una unidad en la tasa de mortalidad infantil, la esperanza de vida disminuye en promedio 0.28 años, todo lo demás constante.
PIB per cápita (b = 6.03e-5, p < 0.001): por cada USD 1.000 adicionales de PIB per cápita, la esperanza de vida aumenta aproximadamente 0.06 años, reflejando que la riqueza material mejora el acceso a salud, nutrición y servicios básicos.
Acceso a agua potable (b = 0.093, p < 0.001): por cada punto porcentual adicional de población con acceso a agua segura, la esperanza de vida aumenta 0.09 años, evidenciando el impacto del saneamiento básico.
Gasto en salud, desempleo y las dummies de ingreso no resultan significativos al 5%.
Residuals vs Fitted: Este gráfico no muestra patrones sistemáticos claros, lo que sugiere que la relación entre las variables independientes y la dependiente es adecuadamente lineal. La dispersión de los residuos alrededor de cero indica que el modelo está bien especificado en términos funcionales.
Q-Q Plot: Los puntos siguen de manera cercana la línea diagonal, lo que indica que los residuos se distribuyen aproximadamente de forma normal. Esto es consistente con el resultado del test de Shapiro-Wilk (p = 0.737), confirmando el cumplimiento del supuesto de normalidad.
Scale-Location (Homocedasticidad): La dispersión de los residuos estandarizados se mantiene relativamente constante a lo largo de los valores ajustados, sin patrones evidentes de aumento o disminución sistemática. Esto sugiere que no existe heterocedasticidad significativa, lo cual es respaldado por el test de Breusch-Pagan.
Residuals vs Leverage: No se observan puntos con alto leverage que influyan de manera desproporcionada en la estimación del modelo. Aunque existen algunas observaciones ligeramente influyentes, ninguna supera los umbrales críticos de la distancia de Cook, lo que indica que el modelo es robusto a valores atípicos.
##
## Shapiro-Wilk normality test
##
## data: residuals(modelo)
## W = 0.99401, p-value = 0.7373
W = 0.994, p = 0.737 – No se rechaza Ho. Los residuales siguen una distribución normal.
##
## studentized Breusch-Pagan test
##
## data: modelo
## BP = 6.3556, df = 8, p-value = 0.6075
BP = 6.356, p = 0.607 – No se rechaza Ho. La varianza de los errores es constante.
vif(modelo) %>%
as.data.frame() %>%
kable(caption = "Tabla 4. Factor de Inflacion de la Varianza") %>%
kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)| GVIF | Df | GVIF^(1/(2*Df)) | |
|---|---|---|---|
| pib_per_capita | 2.514113 | 1 | 1.585595 |
| gasto_salud | 1.262293 | 1 | 1.123518 |
| mortalidad_inf | 2.646119 | 1 | 1.626689 |
| agua_potable | 3.922664 | 1 | 1.980571 |
| desempleo | 1.163123 | 1 | 1.078482 |
| income | 6.891444 | 3 | 1.379489 |
Todos los GVIF^(1/(2xDf)) están por debajo de 2. No hay multicolinealidad problemática.
El modelo de regresión lineal múltiple ajustado para 165 países en 2022 presenta un desempeño sobresaliente (R^2 = 0.924), con todos los supuestos del modelo clásico verificados satisfactoriamente.
Los resultados muestran que la mortalidad infantil es el determinante más crítico de la esperanza de vida. El PIB per cápita confirma la relación positiva entre riqueza y salud, mientras que el acceso a agua potable evidencia el impacto del saneamiento básico sobre la mortalidad por enfermedades prevenibles.
El gasto en salud como porcentaje del PIB no resultó significativo, lo que sugiere que no es el volumen del gasto sino su efectividad lo que realmente determina la longevidad. Desde una perspectiva de política pública, las intervenciones más efectivas son las orientadas a reducir la mortalidad infantil y garantizar acceso universal al agua potable.
Docente Orlando Joaqui. Generación de Informes con RMarkDown. Recuperado de https://juniorjb5.github.io/DataViz/5_Rmarkdown/Class_Rmarkdonw.html#1
World Bank (2023). World Development Indicators. Recuperado de https://databank.worldbank.org/source/world-development-indicators
Arel-Bundock, V. (2022). WDI: World Development Indicators and Other World Bank Data. R package version 2.7.8. https://CRAN.R-project.org/package=WDI
James, G., Witten, D., Hastie, T., y Tibshirani, R. (2021). An Introduction to Statistical Learning. Springer.
Montgomery, D. C., Peck, E. A., y Vining, G. G. (2021). Introduction to Linear Regression Analysis. Wiley.