---
title: "IA para Científicos Sociales"
subtitle: "Sesión 3.3: Laboratorio 5 - Clustering y PCA"
author:
- name: Danilo Freire
orcid: 0000-0002-4712-6810
email: danilofreire@gmail.com
affiliations: "Department of Data and Decision Sciences
Emory University"
format:
clean-revealjs:
self-contained: true
footer: "[Sesión 3.3](https://danilofreire.github.io/introduccion-ia-ucu/clases/dia-03/11-laboratorio-05.html)"
transition: slide
transition-speed: default
scrollable: true
revealjs-plugins:
- multimodal
engine: knitr
editor:
render-on-save: true
lang: es
---
```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
library(knitr)
opts_chunk$set(
prompt = T,
fig.align = "center",
dpi = 300,
cache = T,
engine.opts = list(bash = "-l")
)
knit_hooks$set(
prompt = function(before, options, envir) {
options(
prompt = if (options$engine %in% c("sh", "bash", "zsh")) "$ " else "R> ",
continue = if (options$engine %in% c("sh", "bash", "zsh")) "$ " else "+ "
)
}
)
options(repos = c(CRAN = "https://cran.rstudio.com/"))
if (!require("fontawesome", character.only = TRUE)) {
install.packages("fontawesome", dependencies = TRUE)
library(fontawesome, character.only = TRUE)
}
```
# Laboratorio 5: Clustering y PCA {background-color="#2d4563"}
## Objetivos del laboratorio
:::{style="margin-top: 30px; font-size: 26px;"}
:::{.columns}
:::{.column width=50%}
**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
:::
:::{.column width=50%}
**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]{.alert} 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]{.alert}
:::
# Parte 1: Exploración de datos {background-color="#2d4563"}
## Cargar paquetes
:::{style="margin-top: 30px; font-size: 24px;"}
```{r}
#| label: cargar-paquetes
#| echo: true
#| eval: true
#| message: false
#| warning: false
# Instala los que falten y los carga
paquetes <- c(
"tidyverse",
"tidymodels", # recipe(), step_normalize()
"cluster", # silhouette()
"factoextra", # fviz_cluster(), fviz_nbclust(), fviz_pca(), ...
"corrplot" # matriz de correlación
)
for (pkg in paquetes) {
if (!require(pkg, character.only = TRUE)) {
install.packages(pkg, dependencies = TRUE)
library(pkg, character.only = TRUE)
}
}
set.seed(2026)
```
:::
## Cargar y explorar los datos
:::{style="margin-top: 30px; font-size: 24px;"}
```{r}
#| label: cargar-datos
#| echo: true
#| eval: true
# Cargar indicadores por país
paises <- read_csv("datos/indicadores_paises.csv")
# Lean el archivo directo desde la web:
# paises <- read_csv("https://raw.githubusercontent.com/danilofreire/introduccion-ia-ucu/main/clases/dia-03/datos/indicadores_paises.csv")
# Vista general
glimpse(paises)
```
:::
## Variables del dataset
:::{style="margin-top: 30px; font-size: 26px;"}
| 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) |
:::{style="text-align: center;"}
[Todas las variables son numéricas. Ideal para clustering y PCA]{.alert}
:::
:::
## Estadísticas descriptivas
:::{style="margin-top: 30px; font-size: 24px;"}
```{r}
#| label: estadisticas
#| echo: true
#| eval: true
# Resumen de cada variable
paises |>
select(-pais) |>
summary()
```
Las variables tienen [escalas muy diferentes]{.alert} (PIB en miles vs. índices de 0-10). Es necesario escalar antes de aplicar K-means o PCA
:::
## Matriz de correlación
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: correlacion
#| echo: true
#| eval: true
#| fig-width: 6.5
#| fig-height: 4.5
# Calcular correlaciones
cor_matrix <- paises |>
select(-pais) |>
cor()
# Visualizar
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
:::{style="margin-top: 30px; font-size: 24px;"}
:::{.columns}
:::{.column width=50%}
**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
:::
:::{.column width=50%}
**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"]{.alert}
:::
:::
:::
## Ejercicio rápido: dos países {#sec:ejercicio-paises}
:::{style="margin-top: 30px; font-size: 24px;"}
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]{.alert}?
- ¿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]{.alert}
[[Apéndice: Solución]{.button}](#sec:sol-paises)
:::
## Preparar datos para clustering
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: preparar-datos
#| echo: true
#| eval: true
# Escalar con una receta (media = 0, sd = 1), como en el Día 2
receta_paises <- recipe(~ ., data = paises) |>
update_role(pais, new_role = "id") |>
step_normalize(all_numeric_predictors())
datos_scaled <- receta_paises |> prep() |> juice() |>
column_to_rownames("pais")
head(datos_scaled, 5)
```
[`step_normalize()`]{.alert} 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]{.alert} (empieza con `~`) y `update_role()` marca a `pais` como identificador, no como variable a normalizar
[`column_to_rownames("pais")`]{.alert} 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 {background-color="#2d4563"}
## ¿Qué buscamos con el clustering?
:::{style="margin-top: 30px; font-size: 26px;"}
La [hipótesis]{.alert}: 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:]{.alert} que los grupos tengan sentido sustantivo (países parecidos juntos) y que lo confirmen métricas como la [silueta]{.alert} y el [método del codo]{.alert}
:::
## Ejecutar K-means con K=2
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: kmeans-basico
#| echo: true
#| eval: true
# K-means con 2 clusters
km2 <- kmeans(datos_scaled, centers = 2, nstart = 25)
# Ver resultados
km2$cluster
# Agregar al dataframe original
paises$cluster_km2 <- factor(km2$cluster)
```
:::
## Visualizar los clusters
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: viz-kmeans
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 5
# Visualización con factoextra (usa PCA automáticamente)
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?
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: paises-cluster
#| echo: true
#| eval: true
# Listar países por cluster
paises |>
group_by(cluster_km2) |>
summarise(paises = paste(pais, collapse = ", "))
```
:::
## Perfil de cada cluster
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: perfil-cluster
#| echo: true
#| eval: true
# Medias por cluster (datos originales, no escalados)
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)
)
```
¿Los dos clusters corresponden a "más desarrollados" vs. "menos desarrollados"? ¿En qué variable se diferencian más?
:::
## Método del codo
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: metodo-codo
#| echo: true
#| eval: true
#| fig-width: 6.5
#| fig-height: 4
# Calcular WSS para K=1 a K=8
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]{.alert}
:::
## Método de la silueta
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: metodo-silueta
#| echo: true
#| eval: true
#| fig-width: 6.5
#| fig-height: 4
# Calcular silueta promedio para K=2 a K=8
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]{.alert}
:::
## Interpretación de la silueta
:::{style="margin-top: 30px; font-size: 24px;"}
:::{.columns}
:::{.column width=50%}
**Silueta promedio:**
```{r}
#| label: silueta-promedio
#| echo: true
#| eval: true
# Calcular silueta para cada observación
sil <- silhouette(km2$cluster,
dist(datos_scaled))
mean(sil[, 3])
```
Un valor de ~0.29 indica estructura [débil pero visible]{.alert}
**Observaciones con silueta negativa:**
Están mal clasificadas (más cerca del otro cluster)
:::
:::{.column width=50%}
**Regla de interpretación:**
:::{style="text-align: center;"}
| 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]{.alert}
:::
:::
:::
## Ejercicio rápido: ¿y si probamos K=3? {#sec:ejercicio-k3}
:::{style="margin-top: 30px; font-size: 22px;"}
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]{.alert}
[[Apéndice: Solución]{.button}](#sec:sol-k3)
:::
# Parte 3: PCA e interpretación {background-color="#2d4563"}
## ¿Qué buscamos con el PCA?
:::{style="margin-top: 30px; font-size: 26px;"}
Tenemos 8 variables. PCA las [comprime]{.alert} en pocas dimensiones sin perder mucha información.
**Preguntas que queremos responder:**
- ¿Cuántas dimensiones bastan para resumir las 8 variables?
- ¿Qué [significa]{.alert} 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:]{.alert} que con 2 o 3 componentes expliquemos >70% de la varianza, y que los ejes tengan una interpretación sustantiva clara
:::
## Ejecutar PCA
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: pca-basico
#| echo: true
#| eval: true
# PCA sobre datos escalados
pca <- prcomp(datos_scaled)
# Resumen de varianza explicada
summary(pca)
```
[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]{.alert}
:::
## Scree plot
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: scree-plot
#| echo: true
#| eval: true
#| fig-width: 6.5
#| fig-height: 4
# Varianza explicada por componente
fviz_eig(pca, addlabels = TRUE,
barfill = "#2d4563", barcolor = "#2d4563") +
labs(title = "Scree plot: varianza explicada por componente") +
theme_minimal()
```
:::
## Loadings: ¿qué mide cada componente?
:::{style="margin-top: 30px; font-size: 20px;"}
```{r}
#| label: loadings
#| echo: true
#| eval: true
# Loadings de los primeros 3 componentes
loadings <- pca$rotation[, 1:3] |>
as.data.frame() |>
rownames_to_column("variable") |>
arrange(desc(abs(PC1)))
loadings
```
:::
## Interpretación de PC1 y PC2
:::{style="margin-top: 30px; font-size: 22px;"}
:::{.columns}
:::{.column width=50%}
**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]{.alert}
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
:::
:::{.column width=50%}
**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]{.alert}
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? {#sec:ejercicio-pc1}
:::{style="margin-top: 30px; font-size: 22px;"}
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]{.alert}
[[Apéndice: Solución]{.button}](#sec:sol-pc1)
:::
## Biplot
:::{style="margin-top: 30px; font-size: 20px;"}
```{r}
#| label: biplot
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 5.5
# Biplot con factoextra
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
:::{style="margin-top: 30px; font-size: 24px;"}
:::{.columns}
:::{.column width=50%}
**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
:::
:::{.column width=50%}
**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]{.alert}
:::
# Apéndice: Soluciones de ejercicios rápidos {background-color="#2d4563"}
## Solución: dos países {#sec:sol-paises}
:::{style="margin-top: 20px; font-size: 20px;"}
```{r}
#| label: sol-dos-paises
#| echo: true
#| eval: true
paises |>
filter(pais %in% c("Uruguay", "Honduras")) |>
select(pais, pib = pib_per_capita, internet = acceso_internet,
democracia = indice_democracia, urban = urbanizacion,
gini = indice_gini)
```
- Uruguay tiene PIB per cápita [más de seis veces mayor]{.alert} 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]{.alert} (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]{.button}](#sec:ejercicio-paises)
:::
## Solución: ¿y si probamos K=3? {#sec:sol-k3}
:::{style="margin-top: 20px; font-size: 20px;"}
```{r}
#| label: sol-k3
#| echo: true
#| eval: true
km3 <- kmeans(datos_scaled, centers = 3, nstart = 25)
sil3 <- silhouette(km3$cluster, dist(datos_scaled))
mean(sil3[, 3])
# ¿Qué países quedan en cada cluster?
data.frame(pais = rownames(datos_scaled), cluster = km3$cluster) |>
arrange(cluster)
```
- Silueta con K=3: [≈ 0.27]{.alert} (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:]{.alert} K=3 tiene sentido sustantivo aunque la silueta sea levemente peor
[[Volver al ejercicio]{.button}](#sec:ejercicio-k3)
:::
## Solución: ¿qué país está en los extremos? {#sec:sol-pc1}
:::{style="margin-top: 20px; font-size: 18px;"}
```{r}
#| label: sol-extremos-pc1
#| echo: true
#| eval: true
pca$x[, 1:2] |>
as.data.frame() |>
rownames_to_column("pais") |>
arrange(PC1) |>
mutate(PC1 = round(PC1, 2), PC2 = round(PC2, 2))
```
- 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:]{.alert} 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]{.button}](#sec:ejercicio-pc1)
:::
# Apéndice 1: Clustering jerárquico {background-color="#2d4563"}
## Calcular distancias y dendrograma
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: hclust-basico
#| echo: true
#| eval: true
#| fig-width: 9
#| fig-height: 5
# Matriz de distancias euclidianas
d <- dist(datos_scaled, method = "euclidean")
# Clustering jerárquico con método Ward
hc <- hclust(d, method = "ward.D2")
# Dendrograma con rectángulos para K=2
plot(hc, hang = -1, cex = 0.9,
main = "Dendrograma: Países latinoamericanos",
xlab = "País", ylab = "Altura")
rect.hclust(hc, k = 2, border = c("#2d4563", "#e63946"))
```
:::
## Cortar y comparar con K-means
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: cortar-dendrograma
#| echo: true
#| eval: true
# Cortar para obtener K=2 clusters
grupos_hc <- cutree(hc, k = 2)
# Comparar con K-means
table(K_means = km2$cluster, Jerarquico = grupos_hc)
```
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 {background-color="#2d4563"}
## PCA coloreado por cluster K-means
:::{style="margin-top: 30px; font-size: 20px;"}
```{r}
#| label: pca-cluster
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 5
pca_coords <- pca$x[, 1:2] |>
as.data.frame() |>
rownames_to_column("pais") |>
mutate(cluster = paises$cluster_km2)
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
:::{style="margin-top: 30px; font-size: 22px;"}
```{r}
#| label: contrib-var
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 4
fviz_contrib(pca, choice = "var", axes = 1, fill = "#2d4563") +
labs(title = "Contribución de variables a PC1") +
theme_minimal()
```
:::
# Apéndice 3: Ejercicios adicionales {background-color="#2d4563"}
## Ejercicio: Probar K=4
:::{style="margin-top: 30px; font-size: 22px;"}
**Instrucciones:**
1. Ejecutar K-means con K=4
2. Visualizar los clusters
3. Calcular la silueta
4. ¿Mejora respecto a K=2?
```{r}
#| label: ejercicio-1
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 5
km4 <- kmeans(datos_scaled, centers = 4, nstart = 25)
# Silueta promedio
sil4 <- silhouette(km4$cluster, dist(datos_scaled))
mean(sil4[, 3])
# Visualizar
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
:::{style="margin-top: 30px; font-size: 22px;"}
**Instrucciones:**
1. Extraer los primeros 3 componentes
2. Comparar PC1-PC2 vs. PC1-PC3
3. ¿El tercer componente agrega información útil?
```{r}
#| label: ejercicio-pca3
#| echo: true
#| eval: true
#| fig-width: 8
#| fig-height: 5
pca_3d <- pca$x[, 1:3] |>
as.data.frame() |>
rownames_to_column("pais") |>
mutate(cluster = paises$cluster_km2)
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 {background-color="#2d4563"}