Este dashboard engloba los resultados del proyecto para el modulo 8 del equipo 12, en el cual usamos los datos proporcionado de % GDP usado en gasto publico por pais y por año, así como la esperanza de vida en los diferentes países por año.
Call:
lm(formula = life_expect ~ percent_expenditure_GDP, data = Gasto_expectativa)
Residuals:
Min 1Q Median 3Q Max
-54.746 -4.508 1.759 5.517 18.680
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 63.69835 0.26329 241.93 <2e-16 ***
percent_expenditure_GDP 0.99099 0.03869 25.61 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 8.005 on 5394 degrees of freedom
(9 observations deleted due to missingness)
Multiple R-squared: 0.1084, Adjusted R-squared: 0.1083
F-statistic: 656.1 on 1 and 5394 DF, p-value: < 2.2e-16
[1] "RMSE promedio: 5.8977"
| Feature | Gain | Cover | Frequency |
|---|---|---|---|
| PIB_per_capita | 0.8629544 | 0.4564748 | 0.4101416 |
| percent_expenditure_GDP | 0.1370456 | 0.5435252 | 0.5898584 |
| Row |
Call:
lm(formula = life_expect ~ percent_expenditure_GDP + PIB_per_capita,
data = Gasto_expectativa)
Residuals:
Min 1Q Median 3Q Max
-51.707 -3.721 1.810 4.812 10.865
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 6.397e+01 2.199e-01 290.92 <2e-16 ***
percent_expenditure_GDP 4.894e-01 3.389e-02 14.44 <2e-16 ***
PIB_per_capita 2.327e-04 4.770e-06 48.78 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 6.67 on 5364 degrees of freedom
(15 observations deleted due to missingness)
Multiple R-squared: 0.3824, Adjusted R-squared: 0.3822
F-statistic: 1661 on 2 and 5364 DF, p-value: < 2.2e-16
---
title: "Proyecto_flexdashboard"
output:
flexdashboard::flex_dashboard:
orientation: rows
vertical_layout: fill
theme: cosmo
source_code: embed
navbar:
- { title: "Recursos", href: "#recursos" }
# runtime: shiny
---
```{r setup, include=FALSE}
# Llamamos las librerias a usar
library(flexdashboard)
library(tidyverse)
library(plotly)
library(leaflet)
library(crosstalk)
library(RColorBrewer)
library(viridis)
library(paletteer)
library(ggplot2)
library(kableExtra)
library(htmltools)
library(xgboost)
library(caret)
library(sf)
library(rnaturalearth)
library(rnaturalearthdata)
Gasto_salud <- readr::read_csv("API_SH.XPD.CHEX.GD.ZS_DS2_en_csv_v2_127434.csv", skip = 4)
Expectativa_vida <- readr::read_csv("API_SP.DYN.LE00.IN_DS2_en_csv_v2_130058.csv", skip = 4)
Region <- readr::read_csv("Metadata_Country_API_SH.XPD.CHEX.GD.ZS_DS2_en_csv_v2_127434.csv")
### Vamos a quedarnos solo con los campos sin valores faltantes
Gasto_salud <- Gasto_salud %>%
select(where(~ !all(is.na(.))))
# Ahora, hay algunos paises sin valores del porcentaje de gasto en salud, vamos a dejar solo los paises que si tienen registros. Y quitaremos ambien el año 2023 que tiene casi todos los campos vacios
Gasto_salud <- Gasto_salud %>%
filter(rowSums(is.na(select(., matches("^[0-9]{4}$")))) < length(select(., matches("^[0-9]{4}$")))) %>%
select(-`2023`)
# Ahora que ya tenemos los paises y años que si tienen registros, lo que haremos ahora sera covertir el dataframe a una tabla larga teniendo las columnas:
### Contruy code
### Año
### percent_expenditure_GDP
Gasto_salud <- Gasto_salud %>%
pivot_longer(
cols = matches("^[0-9]{4}$"),
names_to = "Año",
values_to = "percent_expenditure_GDP"
) %>%
select(`Country Name`, `Country Code`, Año, percent_expenditure_GDP)
# Ahora concatenamos año con el codigo del pais para relacionarlo con la tabla de esperanza de vida
Gasto_salud <- Gasto_salud %>%
mutate(Pais_año = paste(`Country Code`, Año, sep = "_")) %>%
select(`Country Name`, `Country Code`, Pais_año, Año, percent_expenditure_GDP)
# Ahora convertimos a tabla larga el dataframe de expectativa de vida y seleccionamos solo las columnas deseadas
Expectativa_vida <- Expectativa_vida %>%
pivot_longer(
cols = matches("^[0-9]{4}$"),
names_to = "Año",
values_to = "life_expect"
) %>%
select(`Country Code`, Año, life_expect)
Expectativa_vida <- Expectativa_vida %>%
mutate(Pais_año = paste(`Country Code`, Año, sep = "_")) %>%
select(Pais_año, life_expect)
############################################################################################################
# Paleta de colores para los valueBox (Set2 = colores suaves bonitos)
paleta_boxes <- RColorBrewer::brewer.pal(3, "Set2")
color_promedio <- paleta_boxes[1]
color_minimo <- paleta_boxes[2]
color_maximo <- paleta_boxes[3]
# Como de la tabla del gasto en salud tenemos solo datos del 2000 a 2022, entonces relacionaremos las tablas con un left join para tener los datos donde si haya registro de gasto en salud. Tambien unimos la tabla de regiones
Region <- Region %>%
select(`Country Code`, Region)
Gasto_expectativa <- left_join(Gasto_salud, Expectativa_vida, by = "Pais_año")
Gasto_expectativa <- left_join(Gasto_expectativa, Region, by = "Country Code")
na_por_pais <- Gasto_expectativa %>%
group_by(`Country Code`) %>%
summarise(
total_obs = n(),
na_expectativa = sum(is.na(life_expect)),
na_gasto_salud = sum(is.na(percent_expenditure_GDP)),
porcentaje_na_salud = round(na_gasto_salud / total_obs * 100, 2)
)
na_por_pais %>%
arrange(desc(na_gasto_salud)) %>%
select(`Country Code`, total_obs, na_gasto_salud, porcentaje_na_salud)
Gasto_expectativa <- Gasto_expectativa %>%
filter(!`Country Code` %in% c("VEN", "SSD", "SOM", "MNE", "ZWE"))
# Con esto tenemos relacionadas las tablas de gasto en salud y de expectativa de vida con los años y paises que si cuentan con regristo.
# Ahora procederemos con los analisis y para responder las preguntas de la tarea
# Empecemos con las medidas para responder a las preguntas de la tarea:
# ¿Qué países presentan el mayor gasto en salud?
# ¿Cómo ha cambiado la esperanza de vida entre 2000 y 2020?
# ¿Existe relación entre gasto en salud y esperanza de vida?
# ¿Hay diferencias regionales claras?
# Encontramos los 15 paises que tienen mayor gasto en salud en promedio.
Top_15_gasto <- Gasto_expectativa %>%
group_by(`Country Name`) %>%
summarise(Gasto_total = mean(percent_expenditure_GDP)) %>%
arrange(desc(Gasto_total)) %>%
slice_head(n = 15)
# Agrupamos el promedio de la esperanza de vida por año para ver comoha cambiado la esperanza de vida entre 2000 y 2020.
Expectativa_año <- Gasto_expectativa %>%
filter(Año >= 2000 & Año <= 2020) %>%
group_by(`Año`) %>%
summarise(Gasto_total = mean(life_expect))
# Hacemos una regresión lineal para ver si existe una relación entre gasto en salud y esperanza de vida
model <- lm(life_expect ~ percent_expenditure_GDP, data = Gasto_expectativa)
# Por la regresión lineal vemos que por cada 1 % de aumento en el porcentaje del GDP de gasto publico, obtenemos un aumento de 0.98 años en la esperanza de vida. Por lo tanto si tiene una relación.
# Ahora agrupamos el promedio de electrativa por region para ver si hay diferencias.
Expectativa_region <- Gasto_expectativa %>%
group_by(`Region`) %>%
summarise(Gasto_total = mean(life_expect))
######
### Ahora, para crear un modelo para relacionar la esperanza de vida con el gasto en salud y controladores socioeconómicos. Usaremos los siguientes controladores socioeconómicos descargados de la pagina del banco mundial:
# GDP per capita (current US$): https://data.worldbank.org/indicator/NY.GDP.PCAP.CD
# Agregamos los datos de PIB per capita
PIB_per_capita <- readr::read_csv("API_NY.GDP.PCAP.CD_DS2_en_csv_v2_134819.csv", skip = 4)
# Convertimos el dataframe a tabla larga
PIB_per_capita <- PIB_per_capita %>%
pivot_longer(
cols = matches("^[0-9]{4}$"),
names_to = "Año",
values_to = "PIB_per_capita"
) %>%
select(`Country Code`, Año, PIB_per_capita)
# Creamos columna concatenada para relacionar con los dataframe anteriores
PIB_per_capita <- PIB_per_capita %>%
mutate(Pais_año = paste(`Country Code`, Año, sep = "_")) %>%
select(Pais_año, PIB_per_capita)
# Agragamos el PIB per capita a nuestro dataframe
Gasto_expectativa <- left_join(Gasto_expectativa, PIB_per_capita, by = "Pais_año")
# Volvemos a buscar valores faltantes para poder realizar los analisis
na_por_pais <- Gasto_expectativa %>%
group_by(`Country Code`) %>%
summarise(
total_obs = n(),
na_pib = sum(is.na(PIB_per_capita)),
porcentaje_na_pib = round(na_pib / total_obs * 100, 2)
)
na_por_pais %>%
arrange(desc(na_pib)) %>%
select(`Country Code`, total_obs, na_pib, porcentaje_na_pib)
# Vemos que el país con su codigo: ERI tiene mas del 47 % de valores faltantes, entonces quitaremos este país para continuar con los analisis.
Gasto_expectativa <- Gasto_expectativa %>%
filter(!`Country Code` %in% c("ERI"))
# Empecemos con el modelo XGBoost
x <- as.matrix(Gasto_expectativa[, c("percent_expenditure_GDP", "PIB_per_capita")])
y <- Gasto_expectativa$life_expect
set.seed(123)
params <- list(
objective = "reg:squarederror",
seed = 123
)
# Entrenamos el modelo
modelo_exp <- xgboost(
data = x,
label = y,
nrounds = 200,
objective = "reg:squarederror",
eta = 0.1,
max_depth = 10,
verbose = 0
)
# Validación cruzada para el modelo de esperanza de vida
cv_result <- xgb.cv(
data = x,
label = y,
nrounds = 100,
nfold = 5,
objective = "reg:squarederror",
metrics = list("rmse", "mae"),
verbose = 0
)
importance_matrix <- xgb.importance(
feature_names = colnames(x),
model = modelo_exp
)
model_2 <- lm(life_expect ~ percent_expenditure_GDP + PIB_per_capita, data = Gasto_expectativa)
########################################################################################################
# Indicadores globales de esperanza de vida
indicadores_globales <- Gasto_expectativa %>%
summarise(
vida_media = mean(life_expect, na.rm = TRUE),
vida_min = min(life_expect, na.rm = TRUE),
vida_max = max(life_expect, na.rm = TRUE)
)
# Serie temporal de esperanza de vida por región (2000–2020)
Expectativa_region_anual <- Gasto_expectativa %>%
filter(Año >= 2000 & Año <= 2020) %>%
group_by(Region, Año) %>%
summarise(
life_expect_mean = mean(life_expect, na.rm = TRUE),
.groups = "drop"
)
# Datos de esperanza de vida por país en 2020
vida_2020 <- Gasto_expectativa %>%
filter(Año == "2020") %>%
group_by(`Country Code`, `Country Name`, Region) %>%
summarise(
life_expect_2020 = mean(life_expect, na.rm = TRUE),
.groups = "drop"
)
# Mapa con los datos de 2020
world <- rnaturalearth::ne_countries(
scale = "medium",
returnclass = "sf"
)
map_data <- world %>%
left_join(vida_2020, by = c("iso_a3" = "Country Code"))
```
Portada
===================
Row
-------------
Este dashboard engloba los resultados del proyecto para el modulo 8 del equipo 12, en el cual usamos los datos proporcionado de % GDP usado en gasto publico por pais y por año, así como la esperanza de vida en los diferentes países por año.
Row
-------------
### Equipo 12:
- Carlos Ivan Pineda Santiago - ivan31416neda@gmail.com
- Oscar Hugo Gómez Díaz - ohgdfac@ciencias.unam.mx
- Jose Alberto Reyes López - j_k_ose@hotmail.com
- Diego Limon Ramos - mareklimath@ciencias.unam.mx
- Daniel Moreno Morales - d.moreno@ciencias.unam.mx
- Victor Andrés Alegría Téllez - v.alegria.data@gmail.com
Preguntas guía
===================
Vamos a ver que dice
-------------
### ¿Qué países presentan el mayor gasto en salud?
```{r}
library(plotly)
p <- ggplot(Top_15_gasto, aes(x = reorder(`Country Name`, -Gasto_total),
y = Gasto_total, fill = `Country Name`)) +
geom_bar(stat = "identity") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "none")
# Convertir a interactivo
ggplotly(p)
```
### ¿Cómo ha cambiado la esperanza de vida entre 2000 y 2020?
```{r}
library(plotly)
p <- ggplot(Expectativa_año, aes(x = Año, y = Gasto_total)) +
geom_line(color = "steelblue") +
geom_point(color = "darkred") +
theme_minimal()
ggplotly(p) %>%
layout(xaxis = list(tickangle = -90))
```
Row
-------------
### ¿Existe relación entre gasto en salud y esperanza de vida?
```{r}
summary(model)
```
- Por la regresión lineal vemos que por cada 1 % de aumento en el porcentaje del GDP de gasto publico, obtenemos un aumento de 0.98 años en la esperanza de vida. Por lo tanto si tiene una relación.
### ¿Hay diferencias regionales claras?
```{r}
library(ggplot2)
library(plotly)
# Gráfico base con ggplot2
p <- ggplot(Expectativa_region, aes(x = Region, y = Gasto_total, fill = Region)) +
geom_col() +
labs(
title = "Expectativa de vida promedio por región",
x = "Región",
y = "Expectativa de vida (años)"
) +
theme_minimal()
# Convertir a interactivo
ggplotly(p) %>%
layout(xaxis = list(tickangle = -90))
```
# Gráfica de dispersión con línea de tendencia
```{r}
library(ggplot2)
library(plotly)
p <- ggplot(Gasto_expectativa, aes(x = life_expect,
y = percent_expenditure_GDP)) +
geom_point(aes(color = Region), size = 3, alpha = 0.7) + # puntos por región
geom_smooth(method = "lm", se = FALSE,
color = "black", fill = "lightgray") + # UNA sola línea
labs(
title = "Relación entre expectativa de vida y gasto en salud",
subtitle = "Puntos coloreados por región, línea global",
x = "Expectativa de vida (años)",
y = "Gasto en salud (% del PIB)"
) +
theme_minimal(base_size = 14)
# Convertir a interactivo
ggplotly(p)
```
Modelo
==============
Row
-------------
###
- Para este modelo agregamos el pib per capita de los países e implementamos XGBoost, teniendo el rango de error:
```{r}
# Mostrar RMSE promedio
print(paste("RMSE promedio:", round(mean(cv_result$evaluation_log$test_rmse_mean), 4)))
```
### Métricas del Modelo
```{r}
library(knitr)
# Mostrar solo las 2 variables y 3 columnas de forma simple
kable(
importance_matrix[1:2, ],
format = "simple",
row.names = FALSE
)
```
Row
-------------
### Variables Importantes
```{r fig.height=4, fig.width=6, echo=FALSE}
library(ggplot2)
# **Cambio:** Mostrar solo el Top 10 para reducir el espacio vertical
top_features <- importance_matrix[1:10, ]
ggplot(top_features, aes(x = reorder(Feature, Gain), y = Gain)) +
geom_bar(stat = "identity", fill = "steelblue") +
coord_flip() +
labs(title = "Top 10 Variables Importantes en XGBoost",
x = "Variables",
y = "Ganancia (Gain)") +
# **Cambio:** Reducir aún más el tamaño de la fuente base y del texto del eje
theme_minimal(base_size = 8) +
theme(
axis.text.y = element_text(size = 7), # Fuente más pequeña para las etiquetas de las variables
plot.title = element_text(size = 10, hjust = 0.5),
plot.margin = margin(2, 2, 2, 2) # Margen más pequeño
)
```
- Vemos que el PIB per capita es la que tiene mayor importancia del modelo XGBoost para explicar el comportamiento de la esperanza de vida.
###
```{r}
summary(model_2)
```
Indicadores globales
===================
Row {.value-boxes}
-------------
### Esperanza de vida promedio
```{r}
valueBox(
value = round(indicadores_globales$vida_media, 1),
caption = "Esperanza de vida promedio (años)",
color = color_promedio
)
```
### Mínimo global
```{r}
valueBox(
value = round(indicadores_globales$vida_min, 1),
caption = "Mínima esperanza de vida observada",
color = color_minimo
)
```
### Máximo global
```{r}
valueBox(
value = round(indicadores_globales$vida_max, 1),
caption = "Máxima esperanza de vida observada",
color = color_maximo
)
```
Row
-------------
### Evolución de la esperanza de vida por región (2000–2020)
```{r}
p_region <- ggplot(
Expectativa_region_anual,
aes(
x = as.numeric(Año),
y = life_expect_mean,
color = Region
)
) +
geom_line() +
theme_minimal() +
labs(
x = "Año",
y = "Esperanza de vida promedio",
color = "Región"
)
ggplotly(p_region)
```
Mapa comparativo
===================
Row {data-height=900}
-------------
### Esperanza de vida por país en 2020
```{r,fig.height=9}
# rangos de edad para hacer seciciones de color claras
breaks_vida <- c(40, 50, 60, 65, 70, 75, 80, 85, 90)
# Paleta por rangos
pal_mapa <- colorBin(
palette = "YlGnBu",
domain = map_data$life_expect_2020,
bins = breaks_vida,
na.color = "transparent"
)
leaflet(map_data) %>%
addTiles() %>%
addPolygons(
fillColor = ~pal_mapa(life_expect_2020),
fillOpacity = 0.8,
color = "#BDBDC3",
weight = 0.2,
label = ~paste0(
name, ": ",
ifelse(
is.na(life_expect_2020),
"sin dato",
paste0(round(life_expect_2020, 1), " años")
)
),
highlightOptions = highlightOptions(
weight = 2,
bringToFront = TRUE
)
) %>%
addLegend(
pal = pal_mapa,
values = ~life_expect_2020,
title = "Esperanza de vida (años, 2020)",
opacity = 0.9,
labFormat = labelFormat(suffix = " años")
)
```
Conclusiones
===================
Row
-------------
### Países con mayor gasto en salud
- De acuerdo con las preguntas guía que se respondieron en su correspondiente sección vemos, como podría ser esperado, que el primer lugar para el país que más realiza gastos en salud es **Estados Unidos**, respondiendo a su condición como una de las economías más grandes y principales del mundo.
- Sorprende, por otro lado, la aparición de países como **Tuvalu** y las **Islas Marshall**, pero esto se justifica por el hecho de que son países sumamente pequeños y con una población menor a los diez mil habitantes, lo cual facilita el gasto en temas de salud.
### Diferencias entre regiones
- Sin embargo, apoyándonos de la gráfica de barras entre regiones vemos que, en general, no se observan diferencias substanciales entre regiones, a excepción de **regiones africanas**, donde sí observamos un avance más lento en el aumento de **esperanza de vida**.
### Relación entre gasto en salud y esperanza de vida
- Por la regresión lineal vemos que, por cada **1 % de aumento** en el porcentaje del **GDP de gasto público**, obtenemos un aumento de **0.98 años** en la **esperanza de vida**.
- Por lo tanto, sí se tiene una **relación** entre el **gasto en salud** y la **esperanza de vida**.
### Impacto de la pandemia
- Por último, es de destacar el cambio en la tendencia ascendente de la **esperanza de vida** en general durante el **2020**, año marcado por la pandemia derivada de la enfermedad **COVID-19**, y que sin duda provocó un cambio drástico en la esperanza de vida humana del cual se tendrá que reponer con los años venideros.