El análisis del desarrollo internacional es fundamental para poder entender las dinámicas económicas, sociales y ambientales a nivel global. El Banco Mundial de Datos, a través de sus Indicadores de Desarrollo (WDI), ofrece un gran repertorio de datos que nos permiten caracterizar naciones. Sin embargo, la complejidad de estos datos, con cientos de variables interrelacionadas, hace mucho más difícil la identificación de patrones y la comparación directa entre países más allá de métricas únicas como el PIB.
El problema central de este estudio es: ¿Cómo podemos agrupar a los países en conjuntos o segmentos homogéneos basándonos en un conjunto multidimensional de indicadores, sin un criterio predefinido?, Pues en este caso se usó el método de aprendizaje no supervisado.
El objetivo de este informe es aplicar técnicas de aprendizaje no supervisado para caracterizar a los países del mundo por grupos (clusters) significativos. Para lograr esto, se utilizó una base de datos del Banco Mundial de Datos para el año 2020. El análisis se realizará en dos partes: primero, se redujo la dimensionalidad de los factores ocultos en el desarrollo. Segundo, se aplicó un método de clusterización jerárquica (Método de Ward) sobre dichos factores para identificar grupos de países con perfiles similares.
# 1. CARGA Y PREPARACIÓN DE DATOS -----------------------------------------
# Cargar datos
datos <- read_csv("datos_banco_mundial_2020.csv")## Rows: 245 Columns: 26
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): Country Name
## dbl (25): PIB_per_capita, Crecimiento_PIB, Exportaciones_PIB, Importaciones_...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Cargar archivo con variables seleccionadas (se espera columna 'Nombre_corto')
vars_sel <- read_csv("variables_seleccionadas.csv")## Rows: 25 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): Codigo, Nombre_corto, Descripcion
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
vars <- vars_sel$Nombre_corto
# Seleccionar variables y columna de país
datos_sel <- datos %>%
select(`Country Name`, all_of(vars))
# Filtrar únicamente observaciones correspondientes a países
# (Se eliminan filas con NA en la mayoría de variables o con nombres de agregados comunes)
# Se eliminan filas con más del 30% de NA en las variables seleccionadas
umbral_na <- ceiling(0.3 * length(vars))
datos_sel <- datos_sel %>%
mutate(n_na = rowSums(is.na(select(., all_of(vars))))) %>%
filter(n_na <= umbral_na) %>%
select(-n_na)
# 2. ANÁLISIS DESCRIPTIVO -----------------------------------------------
# Estadísticas descriptivas básicas
summary_stats <- datos_sel %>%
select(-`Country Name`) %>%
summary()
print("Resumen descriptivo (summary):")## [1] "Resumen descriptivo (summary):"
## PIB_per_capita Crecimiento_PIB Exportaciones_PIB Importaciones_PIB
## Min. : 210 Min. :-54.3361 Min. : 4.549 Min. : 4.83
## 1st Qu.: 1982 1st Qu.: -6.6404 1st Qu.: 20.062 1st Qu.: 24.06
## Median : 5512 Median : -3.3767 Median : 27.914 Median : 33.67
## Mean : 13247 Mean : -4.2586 Mean : 36.061 Mean : 40.95
## 3rd Qu.: 15661 3rd Qu.: -0.9991 3rd Qu.: 41.795 3rd Qu.: 49.40
## Max. :116860 Max. : 43.4797 Max. :204.437 Max. :174.38
## NA's :23 NA's :21
## Ingresos_fiscales_PIB Industria_PIB Agricultura_PIB Poblacion_total
## Min. : 0.000063 Min. : 4.874 Min. : 0.0141 Min. :1.040e+04
## 1st Qu.:11.437249 1st Qu.:19.661 1st Qu.: 2.9598 1st Qu.:2.869e+06
## Median :15.066132 Median :24.670 Median : 7.8547 Median :1.252e+07
## Mean :15.893998 Mean :25.299 Mean :10.6435 Mean :3.545e+08
## 3rd Qu.:20.333478 3rd Qu.:30.935 3rd Qu.:17.3699 3rd Qu.:9.392e+07
## Max. :44.402265 Max. :59.134 Max. :39.2923 Max. :7.855e+09
## NA's :75 NA's :4 NA's :4
## Crecimiento_poblacional Poblacion_urbana Esperanza_vida Gasto_salud_PIB
## Min. :-3.0009 Min. : 13.35 Min. :50.60 Min. : 2.060
## 1st Qu.: 0.2393 1st Qu.: 42.59 1st Qu.:66.46 1st Qu.: 4.966
## Median : 1.0419 Median : 58.02 Median :72.07 Median : 6.460
## Mean : 1.1186 Mean : 59.21 Mean :71.65 Mean : 7.120
## 3rd Qu.: 2.0682 3rd Qu.: 77.40 3rd Qu.:76.97 3rd Qu.: 8.968
## Max. : 5.7257 Max. :100.00 Max. :85.50 Max. :18.813
## NA's :3
## Medicos_por_1000 Mortalidad_infantil Gasto_educacion_PIB Matricula_secundaria
## Min. :0.0340 Min. : 1.600 Min. :6.100e-06 Min. : 30.92
## 1st Qu.:0.6105 1st Qu.: 6.924 1st Qu.:3.389e+00 1st Qu.: 74.44
## Median :2.0360 Median : 17.000 Median :4.305e+00 Median : 91.37
## Mean :2.1208 Mean : 28.464 Mean :4.567e+00 Mean : 87.74
## 3rd Qu.:3.3661 3rd Qu.: 42.850 3rd Qu.:5.306e+00 3rd Qu.:103.02
## Max. :9.1880 Max. :122.600 Max. :1.623e+01 Max. :160.80
## NA's :71 NA's :3 NA's :27 NA's :55
## Matricula_terciaria Usuarios_internet Acceso_electricidad Suscripciones_movil
## Min. : 2.402 Min. : 7.40 Min. : 9.10 Min. : 19.83
## 1st Qu.: 22.455 1st Qu.: 42.28 1st Qu.: 82.78 1st Qu.: 85.25
## Median : 50.533 Median : 70.03 Median : 99.50 Median :106.64
## Mean : 48.097 Mean : 62.60 Mean : 85.77 Mean :106.80
## 3rd Qu.: 71.598 3rd Qu.: 83.94 3rd Qu.:100.00 3rd Qu.:126.01
## Max. :143.693 Max. :100.00 Max. :100.00 Max. :291.92
## NA's :64 NA's :24
## Consumo_electricidad_pc Emisiones_CO2_pc Area_forestal
## Min. : 13.93 Min. : 0.2607 Min. : 0.00
## 1st Qu.: 741.68 1st Qu.: 6.3634 1st Qu.:13.57
## Median : 2262.09 Median : 20.9925 Median :30.42
## Mean : 3885.12 Mean : 30.8129 Mean :32.31
## 3rd Qu.: 4941.67 3rd Qu.: 46.2172 3rd Qu.:45.91
## Max. :50719.99 Max. :253.8147 Max. :94.68
## NA's :52 NA's :5 NA's :2
## Contaminacion_aire_PM25 Energia_renovable
## Min. : 4.895 Min. : 0.00
## 1st Qu.:14.050 1st Qu.:11.00
## Median :21.681 Median :23.40
## Mean :25.056 Mean :32.14
## 3rd Qu.:34.458 3rd Qu.:50.20
## Max. :85.122 Max. :96.20
## NA's :2 NA's :1
El análisis se estructuró en dos partes de la metodología principal:
Parte 1: Análisis de componentes principales (ACP) Para poder manejar la gran dimensionalidad de las 26 variables y el problema de la alta correlación entre los indicadores de desarrollo (multicolinealidad), se realizó un ACP
Reducción de dimensionalidad:Estandarización: Como las variables poseen escalas y unidades de medida muy dispares por ejemplo el “PIB per-capital” en dólares y el “Crecimiento poblacional” en porcentaje, todas las variables se estandarizaron en una escala a media 0 y desviación estándar 1 antes de aplicar el ACP
Reducción: El ACP transforma las 26 variables correlacionadas en un nuevo conjunto de variables no correlacionadas que se denominó “Componentes Principales (o factores). El objetivo fue guardar un número de factores que explicaran una proporción significativa de la varianza total de los datos.
Parte 2: Clusterización jerárquica (Método de Ward) Para poder agrupar los países, se utilizó un método de clusterización jerárquica aglomerativa
Método: Se seleccionó el método de Ward, que se función es minimizar la varizanza total dentro de los clusters, creando grupos compactos y homogéneos posibles
Entrada del modelo: Es importante notar que el clustering no es aplicado en las 26 variables principales, sino sobre las puntuaciones de los 6 primeros factores retenidos en el ACP. Esto permite que el clustering se base en la estructura oculta de los datos , por consiguiente reduce el ruido
Determinación de k: El número optimo de clusters (k) se determinó utilizando el método de la silueta, el cual mide que tan bien está separado un cluster de los vecinos
El análisis se realizó utilizando las librerías “FactoMiner” para ACP, “factoextra” para la visualización y método de la silueta y “tydyverse” para la manipulación de los datos
El análisis descriptivo inicial de las 26 variables para los 144 países muestra el gran incremento en el desarrollo global. Como se oberva en la tabla de estadísticas, variables como “PIB_per-capita” muestra una media de $14,198 con una desviación estándar muy grande, identificando una gran asimetría. Por otra parte, el “crecimiento_PIB” promedio fue de -4.85%, el cual confirma el shock económico global del año 2020.
# Tabla de medias y desviaciones por variable
desc_tabla <- datos_sel %>%
select(-`Country Name`) %>%
summarise_all(list(media = ~mean(. , na.rm = TRUE),
sd = ~sd(. , na.rm = TRUE))) %>%
pivot_longer(everything(), names_to = c("variable",".value"), names_pattern = "(.*)_(.*)")
print("Tabla resumen (media y sd):")## [1] "Tabla resumen (media y sd):"
## # A tibble: 25 × 3
## variable media sd
## <chr> <dbl> <dbl>
## 1 PIB_per_capita 13247. 18172.
## 2 Crecimiento_PIB -4.26 7.59
## 3 Exportaciones_PIB 36.1 29.3
## 4 Importaciones_PIB 40.9 25.8
## 5 Ingresos_fiscales_PIB 15.9 6.40
## 6 Industria_PIB 25.3 9.02
## 7 Agricultura_PIB 10.6 9.41
## 8 Poblacion_total 354499579. 1035223245.
## 9 Crecimiento_poblacional 1.12 1.24
## 10 Poblacion_urbana 59.2 21.8
## # ℹ 15 more rows
La matriz de correlaciones confirma que se necesita el ACP. Se observan grandes correlaciones positivas esperadas, como entre la variable “Esperanza_vida” y “PIB_per-capita”, y entre “Usuarios_internet” y “Matricula_terciaria”. También se observó correlaciones negativas grandes, como entre “Mortalidad_infantil” y “Esperanza de vida”. Esta alta multicolinealidad justifica el unos de la reducción de dimensionalidad.
# Gráficos: distribuciones (boxplot) usando formato largo
data_long <- datos_sel %>%
select(-`Country Name`) %>%
melt()## No id variables; using all as measure variables
ggplot(data_long, aes(x = "", y = value)) +
geom_boxplot() +
facet_wrap(~ variable, scales = "free_y", ncol = 5) +
labs(title = "Boxplot de variables seleccionadas", x = "", y = "Valor (escala libre)") +
# Mejramos la legibilidad
theme(strip.text = element_text(size = 7, face = "bold"),
axis.text.x = element_blank()) # Oculta el texto "" del eje x## Warning: Removed 436 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
# Histograma de la primera variable como ejemplo
prim_var <- vars[1]
ggplot(datos_sel, aes_string(x = prim_var)) +
geom_histogram(bins = 30) +
labs(title = paste("Histograma -", prim_var), x = prim_var, y = "Frecuencia")## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
El ACP fue muy efectivo para la reducción de la dimensionalidad. Como se muestra en la tabla 1 de autovalores, los primero 6 factores poseen un autovalor superor a 1, cumpliendo con el criterio de kaiser para su retención. En conjunto, estos 6 factores logran explicar el 72.4% de la varianza total que estaba contenida en las 26 variables originales. Esto nos brinda una reducción que a nuestro parecer es exitosa, pues convertimos las 26 variables a 6 factores representativos
# 3. REDUCCIÓN DE DIMENSIONALIDAD: ACP -------------------------------------
# Preparar matriz de datos para ACP (imputar NA por la media de cada variable)
datos_numeric <- datos_sel %>%
select(-`Country Name`)
# Imputación simple: reemplazar NA por la media de la variable
for(v in names(datos_numeric)){
datos_numeric[[v]][is.na(datos_numeric[[v]])] <- mean(datos_numeric[[v]], na.rm = TRUE)
}
# Estandarizar y realizar PCA
res.pca <- prcomp(datos_numeric, scale. = TRUE)
# Eigenvalues y proporción de varianza
eig.val <- get_eigenvalue(res.pca)
print(eig.val)## eigenvalue variance.percent cumulative.variance.percent
## Dim.1 9.62318209 38.4927284 38.49273
## Dim.2 2.35900186 9.4360074 47.92874
## Dim.3 1.88392220 7.5356888 55.46442
## Dim.4 1.53741572 6.1496629 61.61409
## Dim.5 1.30071699 5.2028679 66.81696
## Dim.6 1.02937102 4.1174841 70.93444
## Dim.7 0.89853549 3.5941420 74.52858
## Dim.8 0.82202296 3.2880918 77.81667
## Dim.9 0.68712413 2.7484965 80.56517
## Dim.10 0.62746248 2.5098499 83.07502
## Dim.11 0.56359586 2.2543834 85.32940
## Dim.12 0.50167109 2.0066844 87.33609
## Dim.13 0.46168749 1.8467499 89.18284
## Dim.14 0.43894275 1.7557710 90.93861
## Dim.15 0.38459829 1.5383932 92.47700
## Dim.16 0.34918740 1.3967496 93.87375
## Dim.17 0.30881621 1.2352648 95.10902
## Dim.18 0.25814467 1.0325787 96.14159
## Dim.19 0.22185659 0.8874264 97.02902
## Dim.20 0.18956640 0.7582656 97.78729
## Dim.21 0.17602239 0.7040895 98.49138
## Dim.22 0.14518166 0.5807266 99.07210
## Dim.23 0.11940898 0.4776359 99.54974
## Dim.24 0.06016442 0.2406577 99.79040
## Dim.25 0.05240086 0.2096035 100.00000
## Warning in geom_bar(stat = "identity", fill = barfill, color = barcolor, :
## Ignoring empty aesthetic: `width`.
# Interpretación y visualizaciones
fviz_pca_ind(res.pca,
col.ind = "cos2", # Color by the quality of representation
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
repel = TRUE,
title = "Representación de individuos según ACP")fviz_pca_var(res.pca,
col.var = "contrib", # Color by contributions to the PC
gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
repel = TRUE,
title = "Variables - ACP")## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## ℹ The deprecated feature was likely used in the ggpubr package.
## Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
# Obtener coordenadas de los individuos sobre los primeros factores
# Se toman los primeros 3 componentes (ajustable)
n_comp <- 3
pca_scores <- as.data.frame(res.pca$x[, 1:n_comp])
colnames(pca_scores) <- paste0("PC", 1:n_comp)
# Adjuntar nombres de país
pca_scores <- bind_cols(datos_sel %>% select(`Country Name`), pca_scores)Un factor es un “índice sintético”; una nueva “variable” que se construye por parte del modelo que agrupa la información de múltiples variables originales que están correlacionadas
Este primer factor es por mucho el más importante, ya que cubre casi el 40% de toda la información. Este factor representa la dimensión principal y más evidentemente del “desarrollo” en el sentido más amplio. Un país no puede tener una puntuación alta en este factor a no ser que tenga buenos resultados en el siguiente conjunto de características:
Entonces un país con una puntuación alta en el factor 1 es un país con un alto desarrollo socioeconómico, en otras palabras rico, saludable y conectado.
# 4. SEGMENTACIÓN: MÉTODO DE WARD ------------------------------------------
dist_pca <- dist(pca_scores %>% select(starts_with("PC")))
modelo_jerarquico <- hclust(dist_pca, method = "ward.D2")
# Dendrograma
dend_modelo <- as.dendrogram(modelo_jerarquico)
# Añadimos 'leaflab = "none"' para ocultar las etiquetas ilegibles
# y 'ylab' para el eje Y.
plot(dend_modelo,
main = "Dendrograma - Método Ward (sobre factores PCA)",
ylab = "Altura (Distancia)",
leaflab = "none") Determinación del número de clusters (k)
Se utilizó el método de silueta para poder determinar el número optimo de clusters (k) a formar a partir de los 6 factores del ACP. El análisis (Gráfico de la silueta) nos muestra que el puntaje de silueta promedio se maximiza con K=3. Por ende, se procedió a segmentar los 144 países en 3 grupos.
# Determinar número de clusters: silhouette (usando factoextra)
fviz_nbclust(pca_scores %>% select(starts_with("PC")), FUN = hcut, method = "silhouette")# Elegir k (por ejemplo, 3) - en el reporte justificar elección
k <- 3
cluster_labels <- cutree(modelo_jerarquico, k = k)
# Unir etiquetas de cluster al dataset original
clientes_agrupados <- datos_sel %>%
mutate(cluster = factor(cluster_labels))
# Tabla resumen por cluster (medias)
resumen_clusters <- clientes_agrupados %>%
group_by(cluster) %>%
summarise(total = n(),
across(all_of(vars), ~mean(.x, na.rm = TRUE)))Caracterización de los clusters
El análisis de las medias de las variables originales para cada cluster (ver tabla de resumen) nos permite definir 3 perfiles de países claros y distintos:
## [1] "Resumen por cluster (medias):"
## # A tibble: 3 × 27
## cluster total PIB_per_capita Crecimiento_PIB Exportaciones_PIB
## <fct> <int> <dbl> <dbl> <dbl>
## 1 1 67 1410. -0.766 21.0
## 2 2 109 6895. -5.87 31.0
## 3 3 62 37204. -5.20 58.4
## # ℹ 22 more variables: Importaciones_PIB <dbl>, Ingresos_fiscales_PIB <dbl>,
## # Industria_PIB <dbl>, Agricultura_PIB <dbl>, Poblacion_total <dbl>,
## # Crecimiento_poblacional <dbl>, Poblacion_urbana <dbl>,
## # Esperanza_vida <dbl>, Gasto_salud_PIB <dbl>, Medicos_por_1000 <dbl>,
## # Mortalidad_infantil <dbl>, Gasto_educacion_PIB <dbl>,
## # Matricula_secundaria <dbl>, Matricula_terciaria <dbl>,
## # Usuarios_internet <dbl>, Acceso_electricidad <dbl>, …
La visualización de los clusters en el plano factorial, muestra una separación espacial clara entre los grupos
# Visualizaciones: scatter plot de los primeros dos PCs coloreando por cluster
pca_scores_plot <- pca_scores %>%
mutate(cluster = factor(cluster_labels))
ggplot(pca_scores_plot, aes(x = PC1, y = PC2, color = cluster)) +
geom_point(size = 3) +
geom_text(aes(label = `Country Name`), vjust = -1, size = 2.5) +
labs(title = "Clusters sobre primeros dos Componentes Principales") +
theme_minimal()# Boxplots por cluster (variables originales, formato largo)
clientes_long <- clientes_agrupados %>%
pivot_longer(cols = all_of(vars), names_to = "variable", values_to = "valor")
# Ponemos 'cluster' en el eje x para comparar los grupos.
ggplot(clientes_long, aes(x = cluster, y = valor, fill = cluster)) +
geom_boxplot() +
facet_wrap(~ variable, scales = "free_y", ncol = 5) +
labs(title = "Boxplots de variables por cluster", x = "Cluster", y = "Valor (escala libre)") +
# Mejoramos la legibilidad
theme(strip.text = element_text(size = 7, face = "bold"))## Warning: Removed 436 rows containing non-finite outside the scale range
## (`stat_boxplot()`).
Este análisis de aprendizaje no supervisado nos permitió identificas patrones estructurales en el desarrollo global utilizando los datos de 2020. La metodología combinada de ACP y clusterización (Método de Ward) nos mostró ser muy efectiva
Respuesta al problema: El análisis logró caracterizar de manera exitosa a los 144 países en 3 perfiles de desarrollo (Alto, medio y bajo) que no fueron definidos a priori, sino que surgieron de los datos. El modelo pudo identificar cuales variables como el PIB per-capital, la esperanza de vida y el acceso a internet fueron factores descriptivos clave que llevan a la diferenciación de esos grupos
Efectividad del modelo: El ACP demostró ser crucial para reducir la complejidad de las 26 variables elegidas en los 6 factores que explican el 72.4% de la varianza. La clusterización en los factores creó grupos coherentes y estadísticamente justificados (K = 3 según el método de la silueta)
Limitaciones y contextos: Es importante recalcar que estos resultados son una representación del año 2020, el cual fue un año atipico que fue marcado por la pandemia. Indicadores como el Creciemiento PIB negativo (-4.85% en promedio) fueron un reflejo de esta situación
Aplicaciones: Este tipo de caracterización posee unos usos prácticos muy notables. Para organismos internacionales y ONGs, permite ir más allá de las clasificaciones genéricas y diseñar políticas públicas y programas de ayuda más enfocados, adaptados a los perfieles específicos de cada cluster.
World Bank. (2023). World Development Indicators. The World Bank Group. Recuperado de https://databank.worldbank.org/source/world-development-indicators
Kassambara, A. (2017). Practical Guide to Cluster Analysis in R. STHDA.
Husson, F., Lê, S., & Pagès, J. (2017). Exploratory Multivariate Analysis by Example Using R. Chapman and Hall/CRC.
R Core Team (2023). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL https://www.R-project.org/.
Wickham, H. (2016). ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York.
Ward, J. H., Jr. (1963). Hierarchical grouping to optimize an objective function. Journal of the American Statistical Association, 58(301), 236-244.
Pearson, K. (1901). On lines and planes of closest fit to systems of points in space. Philosophical Magazine, 2(11), 559-572.
Hair, J. F., Black, W. C., Babin, B. J., & Anderson, R. E. (2019). Multivariate Data Analysis (8.ª ed.). Cengage Learning.