IA para Científicos Sociales

Sesión 3.3: Laboratorio 5 - Clustering y PCA

Danilo Freire

Department of Data and Decision Sciences
Emory University

Laboratorio 5: Clustering y PCA

Objetivos del laboratorio

Lo que vamos a hacer:

  1. Explorar 8 indicadores de 18 países
  2. Aplicar K-means y evaluar clusters
  3. Usar el método del codo y silueta
  4. Ejecutar PCA e interpretar componentes
  5. Visualizar con biplot

Lo que queremos descubrir:

  • ¿Qué países se parecen entre sí?
  • ¿Cuántos grupos distintos hay?
  • ¿Qué dimensiones ocultas resumen las 8 variables?
  • ¿Es el desarrollo una sola cosa o varias?


Trabajen en sus computadoras. Intenten resolver los ejercicios antes de mirar la solución. Clustering jerárquico y ejercicios adicionales están en los apéndices

Parte 1: Exploración de datos

Cargar paquetes

R> # Instala los que falten y los carga
R> paquetes <- c(
+   "tidyverse",
+   "tidymodels",   # recipe(), step_normalize()
+   "cluster",      # silhouette()
+   "factoextra",   # fviz_cluster(), fviz_nbclust(), fviz_pca(), ...
+   "corrplot"      # matriz de correlación
+ )
R> for (pkg in paquetes) {
+   if (!require(pkg, character.only = TRUE)) {
+     install.packages(pkg, dependencies = TRUE)
+     library(pkg, character.only = TRUE)
+   }
+ }
R> 
R> set.seed(2026)

Cargar y explorar los datos

R> # Cargar indicadores por país
R> paises <- read_csv("datos/indicadores_paises.csv")
R> # Lean el archivo directo desde la web:
R> # paises <- read_csv("https://raw.githubusercontent.com/danilofreire/introduccion-ia-ucu/main/clases/dia-03/datos/indicadores_paises.csv")
R> 
R> # Vista general
R> glimpse(paises)
Rows: 18
Columns: 9
$ pais              <chr> "Argentina", "Bolivia", "Brasil", "Chile", "Colombia…
$ pib_per_capita    <dbl> 10756, 3276, 8942, 15375, 5900, 11745, 5979, 4094, 5…
$ esperanza_vida    <dbl> 76.3, 71.7, 75.8, 80.2, 76.9, 80.7, 77.0, 73.7, 74.6…
$ anios_educacion   <dbl> 10.7, 8.8, 8.1, 10.1, 8.1, 8.9, 8.1, 7.1, 5.4, 6.9, …
$ acceso_internet   <dbl> 86.5, 53.2, 80.1, 87.3, 73.1, 80.2, 64.2, 50.7, 44.3…
$ gasto_salud_pib   <dbl> 10.3, 6.7, 9.7, 9.1, 8.1, 8.0, 8.2, 7.4, 5.6, 7.7, 5…
$ indice_gini       <dbl> 41.3, 44.3, 48.7, 45.4, 50.4, 48.1, 44.9, 38.6, 47.8…
$ urbanizacion      <dbl> 91.7, 69.8, 86.7, 87.3, 81.3, 81.0, 64.0, 73.3, 51.7…
$ indice_democracia <dbl> 6.7, 4.4, 7.0, 8.1, 7.0, 8.3, 5.7, 5.8, 4.9, 5.4, 5.…

Variables del dataset

Variable Descripción
pib_per_capita PIB per cápita en USD
esperanza_vida Esperanza de vida al nacer (años)
anios_educacion Años promedio de escolaridad
acceso_internet % de población con acceso a internet
gasto_salud_pib Gasto en salud como % del PIB
indice_gini Índice de Gini (desigualdad, 0-100)
urbanizacion % de población urbana
indice_democracia Índice de democracia (0-10)

Todas las variables son numéricas. Ideal para clustering y PCA

Estadísticas descriptivas

R> # Resumen de cada variable
R> paises |>
+   select(-pais) |>
+   summary()
 pib_per_capita  esperanza_vida  anios_educacion  acceso_internet
 Min.   : 1881   Min.   :71.70   Min.   : 5.400   Min.   :30.30  
 1st Qu.: 4329   1st Qu.:74.22   1st Qu.: 7.725   1st Qu.:55.70  
 Median : 6108   Median :75.55   Median : 8.300   Median :71.00  
 Mean   : 7971   Mean   :75.87   Mean   : 8.406   Mean   :66.39  
 3rd Qu.:10636   3rd Qu.:76.97   3rd Qu.: 8.975   3rd Qu.:78.80  
 Max.   :17185   Max.   :80.70   Max.   :10.700   Max.   :88.20  
 gasto_salud_pib   indice_gini     urbanizacion   indice_democracia
 Min.   : 4.200   Min.   :38.60   Min.   :51.70   Min.   :2.100    
 1st Qu.: 5.875   1st Qu.:42.58   1st Qu.:65.17   1st Qu.:5.425    
 Median : 7.550   Median :45.50   Median :79.70   Median :6.350    
 Mean   : 7.383   Mean   :45.29   Mean   :75.66   Mean   :6.061    
 3rd Qu.: 8.275   3rd Qu.:48.02   3rd Qu.:85.72   3rd Qu.:6.925    
 Max.   :10.300   Max.   :52.30   Max.   :95.00   Max.   :8.700    

Las variables tienen escalas muy diferentes (PIB en miles vs. índices de 0-10). Es necesario escalar antes de aplicar K-means o PCA

Matriz de correlación

R> # Calcular correlaciones
R> cor_matrix <- paises |>
+   select(-pais) |>
+   cor()
R> 
R> # Visualizar
R> corrplot(cor_matrix, method = "color", type = "upper",
+          addCoef.col = "black", number.cex = 0.7,
+          tl.col = "black", tl.srt = 45,
+          col = colorRampPalette(c("#E74C3C", "white", "#2d4563"))(200))

Interpretación de correlaciones

Correlaciones positivas fuertes:

  • Internet ↔︎ urbanización: 0.86
  • Esperanza de vida ↔︎ democracia: 0.77
  • PIB ↔︎ democracia: 0.76
  • PIB ↔︎ esperanza de vida: 0.74
  • PIB ↔︎ internet: 0.73
  • Internet ↔︎ educación: 0.67

Estas variables “van juntas”: los países con mayor PIB tienen mejor educación, salud, democracia e internet

Correlaciones negativas:

  • Gini ↔︎ urbanización: -0.41
  • Gini ↔︎ internet: -0.26
  • Gini ↔︎ PIB: -0.15

Los países más desiguales tienden a ser menos urbanos y con menor acceso a internet. La correlación Gini ↔︎ democracia es -0.12, casi nula


Varias variables “apuntan en la misma dirección”: el PCA las resumirá en un “eje de desarrollo”

Ejercicio rápido: dos países

Elijan dos países del dataset que les interesen (por ejemplo, Uruguay vs. Honduras, Chile vs. Bolivia, o Argentina vs. Venezuela). Comparen sus valores en las 8 variables.

Preguntas:

  • ¿Cuál parece más desarrollado?
  • ¿En qué variable es mayor la diferencia?
  • ¿Hay alguna variable en la que el “menos desarrollado” supere al otro?

Pista: usen paises |> filter(pais %in% c("...", "...")) y select() con las variables que quieran comparar.

Tómense 3 minutos para experimentar

Apéndice: Solución

Preparar datos para clustering

R> # Escalar con una receta (media = 0, sd = 1), como en el Día 2
R> receta_paises <- recipe(~ ., data = paises) |>
+   update_role(pais, new_role = "id") |>
+   step_normalize(all_numeric_predictors())
R> 
R> datos_scaled <- receta_paises |> prep() |> juice() |>
+   column_to_rownames("pais")
R> 
R> head(datos_scaled, 5)
          pib_per_capita esperanza_vida anios_educacion acceso_internet
Argentina      0.5937295     0.17882893       1.6006861       1.1829170
Bolivia       -1.0007920    -1.71950893       0.2751785      -0.7762995
Brasil         0.2070367    -0.02751214      -0.2131664       0.8063709
Chile          1.5783679     1.78828929       1.1821047       1.2299853
Colombia      -0.4414304     0.42643822      -0.2131664       0.3945236
          gasto_salud_pib indice_gini urbanizacion indice_democracia
Argentina       1.6825368 -1.01330353    1.2641504         0.3835748
Bolivia        -0.3941943 -0.25226889   -0.4613624        -0.9972946
Brasil          1.3364149  0.86391525    0.8701977         0.5636882
Chile           0.9902931  0.02677714    0.9174721         1.2241040
Colombia        0.4134233  1.29516821    0.4447288         0.5636882

step_normalize() hace lo mismo que scale() y es la sintaxis que ya usamos en los laboratorios del Día 2. La receta no tiene variable objetivo (empieza con ~) y update_role() marca a pais como identificador, no como variable a normalizar

column_to_rownames("pais") mueve la columna pais a los nombres de fila, así los nombres de países se preservan automáticamente en todos los plots posteriores (clusters, dendrograma, biplot)

Parte 2: K-means y evaluación

¿Qué buscamos con el clustering?

La hipótesis: los 18 países latinoamericanos no son todos iguales en desarrollo. K-means los dividirá en grupos “parecidos entre sí”.

Preguntas que queremos responder:

  • ¿Cuántos grupos realmente distintos hay? (¿2, 3, 4?)
  • ¿Qué países entran en cada grupo?
  • ¿Los grupos corresponden a niveles de desarrollo, o a otra dimensión?
  • ¿El resultado es estable o sensible al número K elegido?

Métrica de éxito: que los grupos tengan sentido sustantivo (países parecidos juntos) y que lo confirmen métricas como la silueta y el método del codo

Ejecutar K-means con K=2

R> # K-means con 2 clusters
R> km2 <- kmeans(datos_scaled, centers = 2, nstart = 25)
R> 
R> # Ver resultados
R> km2$cluster
           Argentina              Bolivia               Brasil 
                   1                    2                    1 
               Chile             Colombia           Costa Rica 
                   1                    1                    1 
             Ecuador          El Salvador            Guatemala 
                   2                    2                    2 
            Honduras               México            Nicaragua 
                   2                    2                    2 
              Panamá             Paraguay                 Perú 
                   1                    2                    2 
República Dominicana              Uruguay            Venezuela 
                   2                    1                    2 
R> # Agregar al dataframe original
R> paises$cluster_km2 <- factor(km2$cluster)

Visualizar los clusters

R> # Visualización con factoextra (usa PCA automáticamente)
R> fviz_cluster(km2, data = datos_scaled,
+              palette = c("#2d4563", "#e63946"),
+              geom = "point",
+              ellipse.type = "convex",
+              ggtheme = theme_minimal()) +
+   geom_text(aes(label = rownames(datos_scaled)), vjust = -1, size = 3) +
+   labs(title = "K-means con K=2")

¿Qué países están en cada cluster?

R> # Listar países por cluster
R> paises |>
+   group_by(cluster_km2) |>
+   summarise(paises = paste(pais, collapse = ", "))
# A tibble: 2 × 2
  cluster_km2 paises                                                            
  <fct>       <chr>                                                             
1 1           Argentina, Brasil, Chile, Colombia, Costa Rica, Panamá, Uruguay   
2 2           Bolivia, Ecuador, El Salvador, Guatemala, Honduras, México, Nicar…

Perfil de cada cluster

R> # Medias por cluster (datos originales, no escalados)
R> paises |>
+   group_by(cluster_km2) |>
+   summarise(
+     n = n(),
+     pib_mean = round(mean(pib_per_capita)),
+     vida_mean = round(mean(esperanza_vida), 1),
+     educ_mean = round(mean(anios_educacion), 1),
+     inet_mean = round(mean(acceso_internet), 1),
+     gini_mean = round(mean(indice_gini), 1),
+     demo_mean = round(mean(indice_democracia), 1)
+   )
# A tibble: 2 × 8
  cluster_km2     n pib_mean vida_mean educ_mean inet_mean gini_mean demo_mean
  <fct>       <int>    <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
1 1               7    12234      78         9.2      79.8      46.1       7.5
2 2              11     5258      74.5       7.9      57.9      44.8       5.1

¿Los dos clusters corresponden a “más desarrollados” vs. “menos desarrollados”? ¿En qué variable se diferencian más?

Método del codo

R> # Calcular WSS para K=1 a K=8
R> fviz_nbclust(datos_scaled, kmeans,
+              method = "wss",
+              k.max = 8,
+              nstart = 25) +
+   labs(title = "Método del codo",
+        subtitle = "¿Dónde se 'aplana' la curva?") +
+   theme_minimal()

La mayor caída va de K=1 a K=2. Después la curva se aplana: K=2 es el codo

Método de la silueta

R> # Calcular silueta promedio para K=2 a K=8
R> fviz_nbclust(datos_scaled, kmeans,
+              method = "silhouette",
+              k.max = 8,
+              nstart = 25) +
+   labs(title = "Método de la silueta",
+        subtitle = "K óptimo maximiza la silueta promedio") +
+   theme_minimal()

El pico está en K=2. Codo y silueta coinciden: dos grupos es la solución más defendible

Interpretación de la silueta

Silueta promedio:

R> # Calcular silueta para cada observación
R> sil <- silhouette(km2$cluster,
+                   dist(datos_scaled))
R>                   
R> mean(sil[, 3])
[1] 0.2888078

Un valor de ~0.29 indica estructura débil pero visible

Observaciones con silueta negativa:

Están mal clasificadas (más cerca del otro cluster)

Regla de interpretación:

Valor Significado
0.71 - 1.00 Fuerte
0.51 - 0.70 Razonable
0.26 - 0.50 Débil
< 0.25 Sin estructura


Con solo 18 países, es difícil obtener siluetas muy altas

Ejercicio rápido: ¿y si probamos K=3?

Codo y silueta apuntan a K=2, pero K=3 está muy cerca. Prueben dividir los países en 3 grupos y comparen.

Instrucciones:

  1. Ejecuten kmeans(datos_scaled, centers = 3, nstart = 25) y guárdenlo en km3
  2. Calculen la silueta promedio con silhouette(km3$cluster, dist(datos_scaled))
  3. Comparen con la silueta de K=2 (≈ 0.29)

Preguntas:

  • ¿La silueta sube o baja al pasar de K=2 a K=3?
  • ¿Qué países quedan en el cluster “intermedio”?
  • ¿Tiene sentido ese cluster como “desarrollo medio”?

Tómense 3 minutos para experimentar

Apéndice: Solución

Parte 3: PCA e interpretación

¿Qué buscamos con el PCA?

Tenemos 8 variables. PCA las comprime en pocas dimensiones sin perder mucha información.

Preguntas que queremos responder:

  • ¿Cuántas dimensiones bastan para resumir las 8 variables?
  • ¿Qué significa cada dimensión? (¿“desarrollo”? ¿“desigualdad”? ¿otra cosa?)
  • ¿Qué países están en los extremos de cada eje?
  • ¿Los clusters de K-means se separan cuando los vemos en PC1 y PC2?

Métrica de éxito: que con 2 o 3 componentes expliquemos >70% de la varianza, y que los ejes tengan una interpretación sustantiva clara

Ejecutar PCA

R> # PCA sobre datos escalados
R> pca <- prcomp(datos_scaled)
R> 
R> # Resumen de varianza explicada
R> summary(pca)
Importance of components:
                          PC1    PC2    PC3     PC4     PC5    PC6     PC7
Standard deviation     2.0441 1.2575 0.9618 0.76749 0.57816 0.4060 0.38499
Proportion of Variance 0.5223 0.1977 0.1156 0.07363 0.04178 0.0206 0.01853
Cumulative Proportion  0.5223 0.7200 0.8356 0.90926 0.95104 0.9716 0.99017
                           PC8
Standard deviation     0.28043
Proportion of Variance 0.00983
Cumulative Proportion  1.00000

PC1 explica el 52% de la varianza y PC2 el 20%. Entre los dos resumimos el 72% de la información de las 8 variables originales

Scree plot

R> # Varianza explicada por componente
R> fviz_eig(pca, addlabels = TRUE,
+          barfill = "#2d4563", barcolor = "#2d4563") +
+   labs(title = "Scree plot: varianza explicada por componente") +
+   theme_minimal()

Loadings: ¿qué mide cada componente?

R> # Loadings de los primeros 3 componentes
R> loadings <- pca$rotation[, 1:3] |>
+   as.data.frame() |>
+   rownames_to_column("variable") |>
+   arrange(desc(abs(PC1)))
R> 
R> loadings
           variable        PC1         PC2         PC3
1    pib_per_capita -0.4387072  0.07337917 -0.03316035
2   acceso_internet -0.4367711 -0.22750314 -0.09784433
3 indice_democracia -0.4003006  0.28504978  0.27826091
4      urbanizacion -0.3831576 -0.39134175 -0.02000521
5    esperanza_vida -0.3651244  0.43128497 -0.09126237
6   anios_educacion -0.3159903 -0.32026263 -0.53929448
7   gasto_salud_pib -0.2547500  0.39962818  0.31365683
8       indice_gini  0.1079509  0.51007697 -0.71690276

Interpretación de PC1 y PC2

PC1 (52% varianza):

Cargas altas (todas negativas) en:

  • PIB (-0.44), internet (-0.44)
  • Democracia (-0.40), urbanización (-0.38)
  • Esperanza de vida (-0.37), educación (-0.32)

Eje de desarrollo general

Todas estas variables cargan en la misma dirección (negativa): un país con PC1 muy negativo tiene más PIB, democracia e internet. El signo es arbitrario; lo que importa es que van juntas

PC2 (20% varianza):

Cargas altas en:

  • Índice de Gini (0.51)
  • Esperanza de vida (0.43)
  • Gasto en salud (0.40)

Cargas negativas en:

  • Urbanización (-0.39), educación (-0.32)

Contraste desigualdad / urbanización

Separa países desiguales pero con buena salud de países más urbanos y educados

Ejercicio rápido: ¿qué país está en los extremos?

Ordenen los países por su valor en PC1 para identificar los más “desarrollados” y los menos, según esta medida resumen.

Instrucciones:

  1. Extraigan las coordenadas PC1 y PC2 desde pca$x[, 1:2]
  2. Conviertan a data.frame y agreguen los nombres de países con rownames_to_column("pais")
  3. Ordenen por PC1 con arrange(PC1)

Preguntas:

  • ¿Coincide el ranking con su intuición sobre el desarrollo latinoamericano?
  • ¿Qué país les sorprende más (arriba o abajo)?
  • ¿Qué países están cerca de PC1 = 0, en el “medio”?

Tómense 3 minutos para experimentar

Apéndice: Solución

Biplot

R> # Biplot con factoextra
R> fviz_pca_biplot(pca,
+                 repel = TRUE,  # Evita solapamiento de etiquetas
+                 col.var = "#e63946",
+                 col.ind = "#2d4563",
+                 label = "all") +
+   labs(title = "Biplot: países y variables") +
+   theme_minimal()

Resumen del laboratorio

Lo que practicamos:

  • Exploración y escalado de datos
  • K-means con evaluación (codo, silueta)
  • PCA con interpretación de loadings
  • Biplot para visualizar países y variables

Funciones clave:

  • step_normalize(): normalizar datos
  • kmeans(): clustering
  • silhouette(): evaluar clusters
  • prcomp(): PCA
  • fviz_*(): visualizaciones


En el próximo laboratorio aplicaremos análisis de texto. En los apéndices: clustering jerárquico y ejercicios adicionales

Apéndice: Soluciones de ejercicios rápidos

Solución: dos países

R> paises |>
+   filter(pais %in% c("Uruguay", "Honduras")) |>
+   select(pais, pib = pib_per_capita, internet = acceso_internet,
+          democracia = indice_democracia, urban = urbanizacion,
+          gini = indice_gini)
# A tibble: 2 × 6
  pais       pib internet democracia urban  gini
  <chr>    <dbl>    <dbl>      <dbl> <dbl> <dbl>
1 Honduras  2658     38.7        5.4  58.8  52.3
2 Uruguay  17185     88.2        8.7  95    38.9
  • Uruguay tiene PIB per cápita más de seis veces mayor que Honduras (17 185 vs. 2 658)
  • Uruguay supera a Honduras en internet (88% vs. 39%), democracia (8.7 vs. 5.4) y urbanización (95% vs. 59%)
  • Pero Honduras tiene Gini más alto (52.3 vs. 38.9): es más desigual
  • El “desarrollo” no es una sola cosa: hay variables que van en distintas direcciones

Volver al ejercicio

Solución: ¿y si probamos K=3?

R> km3 <- kmeans(datos_scaled, centers = 3, nstart = 25)
R> sil3 <- silhouette(km3$cluster, dist(datos_scaled))
R> mean(sil3[, 3])
[1] 0.2716258
R> # ¿Qué países quedan en cada cluster?
R> data.frame(pais = rownames(datos_scaled), cluster = km3$cluster) |>
+   arrange(cluster)
                                     pais cluster
Bolivia                           Bolivia       1
Ecuador                           Ecuador       1
El Salvador                   El Salvador       1
México                             México       1
Paraguay                         Paraguay       1
Perú                                 Perú       1
República Dominicana República Dominicana       1
Venezuela                       Venezuela       1
Guatemala                       Guatemala       2
Honduras                         Honduras       2
Nicaragua                       Nicaragua       2
Argentina                       Argentina       3
Brasil                             Brasil       3
Chile                               Chile       3
Colombia                         Colombia       3
Costa Rica                     Costa Rica       3
Panamá                             Panamá       3
Uruguay                           Uruguay       3
  • Silueta con K=3: ≈ 0.27 (con K=2 era ≈ 0.29, así que baja un poco)
  • El cluster “intermedio” suele contener países como Bolivia, Ecuador, México, Perú, Paraguay y República Dominicana: desarrollo medio
  • El cluster “bajo” queda como Guatemala, Honduras y Nicaragua: los más pobres
  • Lección: K=3 tiene sentido sustantivo aunque la silueta sea levemente peor

Volver al ejercicio

Solución: ¿qué país está en los extremos?

R> pca$x[, 1:2] |>
+   as.data.frame() |>
+   rownames_to_column("pais") |>
+   arrange(PC1) |>
+   mutate(PC1 = round(PC1, 2), PC2 = round(PC2, 2))
                   pais   PC1   PC2
1               Uruguay -3.45 -0.26
2                 Chile -3.35  0.63
3             Argentina -2.52 -0.89
4            Costa Rica -2.26  1.35
5                Panamá -1.26  1.03
6                Brasil -1.17  0.68
7              Colombia -0.43  0.94
8                México -0.09 -0.92
9  República Dominicana -0.02 -1.56
10                 Perú  0.00 -0.94
11              Ecuador  0.45  0.70
12             Paraguay  0.83  0.05
13          El Salvador  1.33 -0.78
14            Venezuela  1.37 -2.99
15              Bolivia  1.97 -1.12
16             Honduras  2.47  1.87
17            Guatemala  3.03  1.15
18            Nicaragua  3.11  1.05
  • Los valores más negativos de PC1 (Uruguay, Chile, Argentina, Costa Rica, Panamá) son los países más “desarrollados” en este conjunto
  • Los valores más positivos (Honduras, Nicaragua, Guatemala) son los menos desarrollados
  • Sorpresas posibles: Venezuela tiene el PC2 más bajo (-2.99): combina alta urbanización y educación con el menor gasto en salud y la democracia más baja; México sorprende por estar cerca del medio pese a su PIB

Volver al ejercicio

Apéndice 1: Clustering jerárquico

Calcular distancias y dendrograma

R> # Matriz de distancias euclidianas
R> d <- dist(datos_scaled, method = "euclidean")
R> 
R> # Clustering jerárquico con método Ward
R> hc <- hclust(d, method = "ward.D2")
R> 
R> # Dendrograma con rectángulos para K=2
R> plot(hc, hang = -1, cex = 0.9,
+      main = "Dendrograma: Países latinoamericanos",
+      xlab = "País", ylab = "Altura")
R> rect.hclust(hc, k = 2, border = c("#2d4563", "#e63946"))

Cortar y comparar con K-means

R> # Cortar para obtener K=2 clusters
R> grupos_hc <- cutree(hc, k = 2)
R> 
R> # Comparar con K-means
R> table(K_means = km2$cluster, Jerarquico = grupos_hc)
       Jerarquico
K_means  1  2
      1  7  0
      2  0 11

Los números de cluster son arbitrarios (cluster 1 en K-means puede ser cluster 2 en jerárquico). Lo importante es si los grupos de países coinciden

Apéndice 2: PCA avanzado

PCA coloreado por cluster K-means

R> pca_coords <- pca$x[, 1:2] |>
+   as.data.frame() |>
+   rownames_to_column("pais") |>
+   mutate(cluster = paises$cluster_km2)
R> 
R> ggplot(pca_coords, aes(x = PC1, y = PC2, color = cluster, label = pais)) +
+   geom_point(size = 3) +
+   geom_text(vjust = -0.8, size = 3, show.legend = FALSE) +
+   scale_color_manual(values = c("#2d4563", "#e63946")) +
+   labs(title = "PCA coloreado por cluster K-means",
+        x = paste0("PC1 (", round(summary(pca)$importance[2,1]*100, 1), "%)"),
+        y = paste0("PC2 (", round(summary(pca)$importance[2,2]*100, 1), "%)")) +
+   theme_minimal()

Contribución de variables a cada componente

R> fviz_contrib(pca, choice = "var", axes = 1, fill = "#2d4563") +
+   labs(title = "Contribución de variables a PC1") +
+   theme_minimal()

Apéndice 3: Ejercicios adicionales

Ejercicio: Probar K=4

Instrucciones:

  1. Ejecutar K-means con K=4
  2. Visualizar los clusters
  3. Calcular la silueta
  4. ¿Mejora respecto a K=2?
R> km4 <- kmeans(datos_scaled, centers = 4, nstart = 25)
R> 
R> # Silueta promedio
R> sil4 <- silhouette(km4$cluster, dist(datos_scaled))
R> mean(sil4[, 3])
[1] 0.2354994
R> # Visualizar
R> fviz_cluster(km4, data = datos_scaled,
+              palette = c("#2d4563", "#e63946", "#457b9d", "#f4a261"),
+              ggtheme = theme_minimal()) +
+   labs(title = "K-means con K=4")

Ejercicio: PCA con 3 componentes

Instrucciones:

  1. Extraer los primeros 3 componentes
  2. Comparar PC1-PC2 vs. PC1-PC3
  3. ¿El tercer componente agrega información útil?
R> pca_3d <- pca$x[, 1:3] |>
+   as.data.frame() |>
+   rownames_to_column("pais") |>
+   mutate(cluster = paises$cluster_km2)
R> 
R> ggplot(pca_3d, aes(x = PC1, y = PC3, color = cluster, label = pais)) +
+   geom_point(size = 3) +
+   geom_text(vjust = -0.8, size = 3, show.legend = FALSE) +
+   scale_color_manual(values = c("#2d4563", "#e63946")) +
+   labs(title = "PC1 vs PC3") +
+   theme_minimal()

Continuar con el laboratorio de texto