A31-Análisis de Clúster (Conglomerados)
UNIVERSIDAD DE EL SALVADOR
FACULTAD DE CIENCIAS ECONÓMICAS
ESCUELA DE ECONOMÍA
Ciclo II - 2025
“Análisis de Clúster (Conglomerados)”
Asignatura:
Métodos para el Análisis Económico
Grupo teórico:
GT-01
Docente:
MSF Carlos Ademir Pérez Alas
Integrantes:
Rosa Audelia Hernández Herrera — HH23026
Fátima Carolina Guillén Aguilar — GA22013
José Ricardo Vides Hernández — VH22011
Ciudad Universitaria, San Salvador – 17 de noviembre de 2025
1. Análisis de conglomerados
Definición de análisis de conglomerados
“El análisis de conglomerados es uno de los métodos importantes de minería de datos para descubrir conocimiento en datos multidimensionales. El objetivo del análisis de conglomerados es identificar patrones o grupos de objetos similares dentro de un conjunto de datos de interés.” (Kassambara, 2017, p. 3)
El análisis de conglomerados es una herramienta estadística que se utiliza para agrupar observaciones, personas, empresas o cualquier tipo de objeto en categorías llamadas “conglomerados” o “clusters”, de modo que los elementos dentro de un mismo grupo sean lo más parecidos posibles entre sí y, al mismo tiempo, diferentes de los pertenecientes a otros grupos.
Lo interesante del análisis de clúster es que no requiere una variable dependiente ni hipótesis previas, sino que deja que los datos “hablen por sí mismos”, revelando patrones ocultos o estructuras naturales en la información. Por eso se le considera parte de las técnicas de aprendizaje automático no supervisado
2. Cuadro comparativo
|
Cuadro Comparativo |
|||
|
Análisis de Clúster |
Técnicas disponibles |
Ventajas |
Desventajas |
|
Jerárquico: Este tipo de análisis agrupa los datos de manera progresiva o jerárquica, como si construyéramos un “árbol de relaciones”. Comienza tomando cada observación como un grupo individual y luego las va uniendo según su similitud, hasta formar grupos más grandes. El resultado se representa visualmente con un dendrograma, que muestra cómo los grupos se combinan paso a paso. Estos métodos permiten visualizar las relaciones entre observaciones sin necesidad de definir previamente el número de conglomerados. |
Métodos aglomerativos: • Single Linkage (Vecino más próximo) • Complete Linkage (Vecino más lejano) • Average Linkage (Promedio entre grupos) • Método del Centroide • Método de la Mediana • Método de Ward
Métodos divisivos (disociativos): • DIANA (Divisive Analysis Clustering)* |
• No necesito saber cuántos grupos hay desde el inicio.
• Permite ver la formación de los grupos paso a paso.
• Es bueno para explorar los datos por primera vez.
• Ayuda a identificar observaciones raras o atípicas.
|
• No funciona bien cuando hay demasiados datos.
• Es muy sensible a valores extremos.
• Una vez une dos grupos, ya no hay marcha atrás.
• A veces crea grupos muy desbalanceados. |
|
No jerárquico: El análisis de conglomerados no jerárquico parte de un número predeterminado de grupos (k), y busca la mejor partición de los datos asignando cada observación al conglomerado más cercano según una medida de distancia. Kassambara (2017) indica que estos métodos son más eficientes computacionalmente y adecuados para grandes conjuntos de datos. |
Métodos de reasignación: • K-Means (centroides basados en medias) • K-Medoids (PAM) (centroides basados en objetos reales) • CLARA (Cluster Large Applications)
Métodos basados en densidad o forma: • DBSCAN (Density-Based Spatial Clustering) • Fuzzy C-Means (Clustering difuso)
Otros métodos directos o reductivos: • Block Clustering • Análisis factorial tipo Q |
• Es mucho más rápido y eficiente. Cuando trabajo con muchos datos, los métodos no jerárquicos (especialmente K-means) pueden procesarlos sin problema. Es ideal para bases grandes.
• Los grupos pueden reajustarse en cada iteración. Los algoritmos mueven los puntos entre grupos hasta encontrar la mejor combinación posible. Esto ayuda a obtener grupos más “limpios”.
• Algunos métodos son muy robustos a valores atípicos.
• Si ya sé cuántos grupos quiero, es la mejor opción.
|
• Tengo que decir cuántos grupos quiero antes de empezar.
• La solución depende mucho de cómo inicia el algoritmo. Por ejemplo, K-means puede encontrar grupos diferentes dependiendo de los valores iniciales. Hay que fijar una semilla y probar varias veces.
• Si no estandarizo las variables, el resultado puede ser engañoso.
• Algunos métodos requieren parámetros adicionales difíciles de elegir.
|
Fuente: Elaboración propia con base en Kassambara (2017) y De la Fuente Fernández (2014).
3. Librería y sintaxis en R
Métodos Jerarquicos
Los métodos jerárquicos construyen una estructura llamada dendrograma, que representa cómo las observaciones se van juntando (o separando) según su similitud. La característica esencial es que no necesitas definir cuántos clústeres quieres antes de comenzar, ya que el dendrograma muestra todas las posibles agrupaciones.
Métodos Jerárquicos Aglomerativos
En estos métodos, cada observación comienza siendo su propio grupo. Luego, poco a poco, se fusionan los grupos más similares. La forma en que se decide cuáles grupos se unen depende de la técnica o criterio de enlace (linkage). Ese criterio determina cómo se mide la distancia entre dos grupos.
Estrutura General en R
# Preparar datos
df <- USArrests
df <- na.omit(df)
df <- scale(df)
# Matriz de distancias
d <- dist(df)
# Métodos jerárquicos aglomerativos
hc_single <- hclust(d, method = "single")
hc_complete <- hclust(d, method = "complete")
hc_average <- hclust(d, method = "average")
hc_centroid <- hclust(d, method = "centroid")
hc_median <- hclust(d, method = "median")
hc_ward <- hclust(d, method = "ward.D2")Antes de usar hclust(), debemos convertir el df estandarizado en una matriz de distancias: d <- dist(df)
Donde: hclust() es la función universal de clustering jerárquico aglomerativo en R:
hclust(d, …) = Primer argumento: la matriz de distancias hclust(d, method = “single”) = Segundo argumento: method = “single”, este parámetro le dice a R: “¿Cómo quieres que mida la distancia entre clústeres cuando tenga que unirlos?”
“single” → une los clústeres si tienen puntos muy cercanos
“complete” → une los clústeres si todos los puntos están cerca
“average” → promedio de distancias
“centroid” → distancia entre centroides
“median” → distancia entre medianas
“ward.D” o “ward.D2” → método de mínima varianza
Formas especificas
• Single Linkage (Vecino más próximo)
Esta técnica une los clústeres que tienen al menos dos puntos muy cercanos entre sí. Es decir, si existe un par de observaciones —una en cada grupo— que están muy cerca, entonces los grupos se consideran similares.
• Complete Linkage (Vecino más lejano)
Considera que dos clústeres son similares sólo si todos sus puntos están relativamente cerca entre sí. Busca que los grupos formados sean compactos y de forma relativamente redonda.
• Average Linkage (Promedio)
Mide la similitud entre grupos usando el promedio de todas las distancias entre sus observaciones. Es una técnica intermedia entre single y complete.
• Centroid Linkage (Método del centroide)
Cada clúster se representa por el punto promedio de sus observaciones (el centroide). Se unen los clústeres cuyos centroides están más cerca.
• Median Linkage (Método de la mediana)
Parecido al centroide, pero los clústeres se representan por su mediana en cada variable, lo que lo hace más robusto a valores extremos.
• Ward’s Method (Mínima varianza interna)
Ward une los grupos de tal forma que el aumento en la variación interna del nuevo clúster sea el más pequeño posible. Es decir, siempre busca crear clústeres compactos y homogéneos.
Métodos Jerárquicos Divisivos
• DIANA (Divisive Analysis Clustering)
DIANA es el inverso del método aglomerativo:
Empieza con un solo clúster que contiene todos los datos. Busca los puntos más distintos entre sí para separar un subgrupo y en cada paso divide el clúster más heterogéneo.
library(cluster)
res.diana <- diana(df, stand = FALSE)
#Si queremos ser más explicito y apegarnos más a la forma de Kassambara podemos usar esta forma: diana(x, stand = FALSE, metric = "euclidean")Entonces:
diana(df) recibe datos ya estandarizados.
stand = TRUE aquí es redundante (doble estandarización), por eso usamos el argumento FALSE
Como no especificas metric, DIANA usa por defecto “euclidean”.
Métodos No Jérarquicos
Los métodos no jerárquicos de cluster son técnicas de particionamiento que optan por dividir directamente los datos en grupos, sin construir el “árbol” (dendrograma) característico de los métodos jerárquicos. Su funcionamiento se basa en la reasignación iterativa de cada punto de dato: comienzan con una división inicial y luego mueven y ajustan continuamente los puntos hasta que se alcanza una solución estable (convergencia), donde los grupos están bien definidos. La mayoría de estos algoritmos requiere que el analista defina primero la cantidad de grupos deseada, (exceptuando métodos avanzados basados en densidad como DBSCAN). Al centrarse en esta optimización directa e iterativa, son intrínsecamente más rápidos y eficientes para procesar grandes volúmenes de datos, lo que los convierte en la herramienta predilecta para el análisis a gran escala.
Métodos de reasignación
Minimizar la variación interna dentro de cada grupo y maximizar la separación entre grupos.
Es decir, estos métodos funcionan tal que así:
Se elige aleatoriamente un número de k clústeres.
Cada observación se asigna provisionalmente a uno de ellos.
Se mide qué tan buena es la agrupación (homogeneidad interna).
Se reasignan observaciones si eso mejora la calidad.
5 .Continúa hasta que las asignaciones ya no cambian.
Estrutura General en R
#df <- scale(USArrests), si fuese necesario prepar los datos
km <- kmeans(df, centers = 4)
pam_res <- pam(df, k = 4)
clara_res <- clara(df, k = 4)Donde: Función(df, parámetro del número de clústeres): df → es el dataset numérico (preferiblemente estandarizado) centers / k → número de clústeres que quieres formar función → indica el algoritmo usado: kmeans, pam o clara.
Formas especificas
•K-MEANS
K-means crea clústeres representados por un centroide, que no es una observación real sino un punto promedio. Cada observación se asigna al clúster cuyo centroide esté más cerca. Luego, los centroides se recalculan y se vuelve a asignar.
set.seed(123)
km <- kmeans(df, centers = 4, nstart = 25)
# km$cluster (categoría asignada a cada observación)
# km$centers (centroides de cada clúster)• K-MEDOIDS (PAM)
Igual que K-means, pero aquí cada clúster se representa con un medoid, que es una observación real, no un promedio.
library(cluster)
pam_res <- pam(df, k = 2)
# pam_res$clustering (asignación de cada punto)
# pam_res$medoids (observaciones representativas)• CLARA (Clustering Large Applications)
CLARA es una versión de PAM diseñada para bases muy grandes. En lugar de aplicar PAM a toda la base, toma submuestras aleatorias, ejecuta PAM, y conserva la mejor solución.
Métodos de densidad o forma
Aquí, un clúster se define como:
“Una región donde los puntos están más densamente concentrados que en otras partes del espacio.”
Estos métodos detectan:
clústeres de formas arbitrarias (curvas, anillos, figuras no esféricas),
outliers de forma natural
regiones dispersas como “ruido”.
No requieren especificar k.
Estrutura General en R
Donde:
dbscan::dbscan(df, eps, minPts)
df→ Dataset numérico estandarizado.
eps→ Radio máximo dentro del cual los puntos se consideran vecinos.
minPts→ Número mínimo de vecinos dentro de eps para formar un clúster.
fanny(df, k)
df→ Dataset numérico.
k→ Número de clústeres difusos a generar.
Formas especificas
• DBSCAN
DBSCAN agrupa puntos que están suficientemente cerca unos de otros en términos de densidad.
Se sigue esta forma de obtener los resultados siguiendo los dichos de Kassambara: Here, we’ll use the R package fpc to compute DBSCAN. It’s also possible to use the package dbscan, which provides a faster re-implementation of DBSCAN algorithm compared to the fpc package (Kassambara, 2017, p. 182).
•FUZZY C-MEANS
Parecido a K-means, pero en vez de asignar cada punto a un único clúster, asigna porcentajes de pertenencia.
4. Ejemplos desarrollados
Replica de ejemplos de capitulo 4
Cargar y estandarizar los datos (USArrests)
## Murder Assault UrbanPop Rape
## Alabama 1.24256408 0.7828393 -0.5209066 -0.003416473
## Alaska 0.50786248 1.1068225 -1.2117642 2.484202941
## Arizona 0.07163341 1.4788032 0.9989801 1.042878388
Determinar el número óptimo de clusters (método del codo – WSS)
library(factoextra)
library(ggplot2)
library(ggrepel)
fviz_nbclust(df, kmeans, method = "wss") +
geom_vline(xintercept = 4, linetype = 2)Ejecutar K-means con k = 4
## K-means clustering with 4 clusters of sizes 8, 13, 16, 13
##
## Cluster means:
## Murder Assault UrbanPop Rape
## 1 1.4118898 0.8743346 -0.8145211 0.01927104
## 2 -0.9615407 -1.1066010 -0.9301069 -0.96676331
## 3 -0.4894375 -0.3826001 0.5758298 -0.26165379
## 4 0.6950701 1.0394414 0.7226370 1.27693964
##
## Clustering vector:
## Alabama Alaska Arizona Arkansas California
## 1 4 4 1 4
## Colorado Connecticut Delaware Florida Georgia
## 4 3 3 4 1
## Hawaii Idaho Illinois Indiana Iowa
## 3 2 4 3 2
## Kansas Kentucky Louisiana Maine Maryland
## 3 2 1 2 4
## Massachusetts Michigan Minnesota Mississippi Missouri
## 3 4 2 1 4
## Montana Nebraska Nevada New Hampshire New Jersey
## 2 2 4 2 3
## New Mexico New York North Carolina North Dakota Ohio
## 4 4 1 2 3
## Oklahoma Oregon Pennsylvania Rhode Island South Carolina
## 3 3 3 3 1
## South Dakota Tennessee Texas Utah Vermont
## 2 1 4 3 2
## Virginia Washington West Virginia Wisconsin Wyoming
## 3 3 2 2 3
##
## Within cluster sum of squares by cluster:
## [1] 8.316061 11.952463 16.212213 19.922437
## (between_SS / total_SS = 71.2 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Promedios por cluster y unión con el dataset original
## cluster Murder Assault UrbanPop Rape
## 1 1 13.93750 243.62500 53.75000 21.41250
## 2 2 3.60000 78.53846 52.07692 12.17692
## 3 3 5.65625 138.87500 73.87500 18.78125
## 4 4 10.81538 257.38462 76.00000 33.19231
## Murder Assault UrbanPop Rape cluster
## Alabama 13.2 236 58 21.2 1
## Alaska 10.0 263 48 44.5 4
## Arizona 8.1 294 80 31.0 4
## Arkansas 8.8 190 50 19.5 1
## California 9.0 276 91 40.6 4
## Colorado 7.9 204 78 38.7 4
Asignación de cluster para cada observación
## Alabama Alaska Arizona Arkansas
## 1 4 4 1
Centros (centroides) de los clusters
## Murder Assault UrbanPop Rape
## 1 1.4118898 0.8743346 -0.8145211 0.01927104
## 2 -0.9615407 -1.1066010 -0.9301069 -0.96676331
## 3 -0.4894375 -0.3826001 0.5758298 -0.26165379
## 4 0.6950701 1.0394414 0.7226370 1.27693964
Replica de ejemplos capitulo 5
Cargar y estandarizar datos
## Murder Assault UrbanPop Rape
## Alabama 1.24256408 0.7828393 -0.5209066 -0.003416473
## Alaska 0.50786248 1.1068225 -1.2117642 2.484202941
## Arizona 0.07163341 1.4788032 0.9989801 1.042878388
Determinar número óptimo de clusters (silhouette)
Ejecutar PAM con k = 2
## Medoids:
## ID Murder Assault UrbanPop Rape
## New Mexico 31 0.8292944 1.3708088 0.3081225 1.1603196
## Nebraska 27 -0.8008247 -0.8250772 -0.2445636 -0.5052109
## Clustering vector:
## Alabama Alaska Arizona Arkansas California
## 1 1 1 2 1
## Colorado Connecticut Delaware Florida Georgia
## 1 2 2 1 1
## Hawaii Idaho Illinois Indiana Iowa
## 2 2 1 2 2
## Kansas Kentucky Louisiana Maine Maryland
## 2 2 1 2 1
## Massachusetts Michigan Minnesota Mississippi Missouri
## 2 1 2 1 1
## Montana Nebraska Nevada New Hampshire New Jersey
## 2 2 1 2 2
## New Mexico New York North Carolina North Dakota Ohio
## 1 1 1 2 2
## Oklahoma Oregon Pennsylvania Rhode Island South Carolina
## 2 2 2 2 1
## South Dakota Tennessee Texas Utah Vermont
## 2 1 1 2 2
## Virginia Washington West Virginia Wisconsin Wyoming
## 2 2 2 2 2
## Objective function:
## build swap
## 1.441358 1.368969
##
## Available components:
## [1] "medoids" "id.med" "clustering" "objective" "isolation"
## [6] "clusinfo" "silinfo" "diss" "call" "data"
Unir datos originales con su asignación de cluster
## Murder Assault UrbanPop Rape cluster
## Alabama 13.2 236 58 21.2 1
## Alaska 10.0 263 48 44.5 1
## Arizona 8.1 294 80 31.0 1
Medoids del clustering
## Murder Assault UrbanPop Rape
## New Mexico 0.8292944 1.3708088 0.3081225 1.1603196
## Nebraska -0.8008247 -0.8250772 -0.2445636 -0.5052109
Asignación de cada observación al cluster
## Alabama Alaska Arizona Arkansas California Colorado
## 1 1 1 2 1 1
Replica de ejemplos capitulo 6
Generar datos artificiales para aplicar CLARA
set.seed(1234)
df <- rbind(cbind(rnorm(200,0,8), rnorm(200,0,8)),
cbind(rnorm(300,50,8), rnorm(300,50,8)))
colnames(df) <- c("x", "y")
rownames(df) <- paste0("S", 1:nrow(df))
head(df, nrow = 6)## x y
## S1 -9.656526 3.881815
## S2 2.219434 5.574150
## S3 8.675529 1.484111
## S4 -18.765582 5.605868
## S5 3.432998 2.493448
## S6 4.048447 6.083699
Determinar el número óptimo de clusters (silhouette)
library(cluster)
library(factoextra)
fviz_nbclust(df, clara, method = "silhouette")+
theme_classic()Ejecutar CLARA
## Call: clara(x = df, k = 2, samples = 50, pamLike = TRUE)
## Medoids:
## x y
## S121 -1.531137 1.145057
## S455 48.357304 50.233499
## Objective function: 9.87862
## Clustering vector: Named int [1:500] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ...
## - attr(*, "names")= chr [1:500] "S1" "S2" "S3" "S4" "S5" "S6" "S7" ...
## Cluster sizes: 200 300
## Best sample:
## [1] S37 S49 S54 S63 S68 S71 S76 S80 S82 S101 S103 S108 S109 S118 S121
## [16] S128 S132 S138 S144 S162 S203 S210 S216 S231 S234 S249 S260 S261 S286 S299
## [31] S304 S305 S312 S315 S322 S350 S403 S450 S454 S455 S456 S465 S488 S497
##
## Available components:
## [1] "sample" "medoids" "i.med" "clustering" "objective"
## [6] "clusinfo" "diss" "call" "silinfo" "data"
Unir clusters con datos originales
## x y cluster
## S1 -9.656526 3.881815 1
## S2 2.219434 5.574150 1
## S3 8.675529 1.484111 1
## S4 -18.765582 5.605868 1
Asignación a clusters
## S1 S2 S3 S4 S5 S6 S7 S8 S9 S10
## 1 1 1 1 1 1 1 1 1 1
Replica de ejemplos capitulo 7
Cargar y estandarizar datos
## Murder Assault UrbanPop Rape
## Alabama 1.24256408 0.7828393 -0.5209066 -0.003416473
## Alaska 0.50786248 1.1068225 -1.2117642 2.484202941
## Arizona 0.07163341 1.4788032 0.9989801 1.042878388
## Arkansas 0.23234938 0.2308680 -1.0735927 -0.184916602
## California 0.27826823 1.2628144 1.7589234 2.067820292
## Colorado 0.02571456 0.3988593 0.8608085 1.864967207
Mostrar parte de la matriz de distancias
## Alabama Alaska Arizona Arkansas California Colorado
## Alabama 0.000000 2.703754 2.293520 1.289810 3.263110 2.651067
## Alaska 2.703754 0.000000 2.700643 2.826039 3.012541 2.326519
## Arizona 2.293520 2.700643 0.000000 2.717758 1.310484 1.365031
## Arkansas 1.289810 2.826039 2.717758 0.000000 3.763641 2.831051
## California 3.263110 3.012541 1.310484 3.763641 0.000000 1.287619
## Colorado 2.651067 2.326519 1.365031 2.831051 1.287619 0.000000
Distancia cophenética y correlación
## [1] 0.6975266
Comparación con método average
## [1] 0.7180382
Cortar dendrograma en 4 grupos
## Alabama Alaska Arizona Arkansas
## 1 2 2 3
Miembros del cluster 1
## [1] "Alabama" "Georgia" "Louisiana" "Mississippi"
## [5] "North Carolina" "South Carolina" "Tennessee"
Visualización del dendrograma con colores
fviz_dend(res.hc, k = 4,
cex = 0.5,
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE,
rect = TRUE
)Visualización de clusters en el espacio original
fviz_cluster(list(data = df, cluster = grp),
palette = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
ellipse.type = "convex",
repel = TRUE,
show.clust.cent = FALSE, ggtheme = theme_minimal())Métodos aglomerativo (agnes) y divisivo (diana)
Replica de ejemplo capitulo 8
Selección aleatoria de 10 observaciones
Construcción de dos dendrogramas con métodos diferentes
Tanglegram mejorado
tanglegram(dend1, dend2,
highlight_distinct_edges = FALSE,
common_subtrees_color_lines = FALSE,
common_subtrees_color_branches = TRUE,
main = paste("entanglement =", round(entanglement(dend_list), 2))
)Correlación cophenética
## [,1] [,2]
## [1,] 1.0000000 0.9925544
## [2,] 0.9925544 1.0000000
Correlación Baker
## [,1] [,2]
## [1,] 1.0000000 0.9895528
## [2,] 0.9895528 1.0000000
Comparación de múltiples métodos jerárquicos
dend1 <- df %>% dist %>% hclust("complete") %>% as.dendrogram
dend2 <- df %>% dist %>% hclust("single") %>% as.dendrogram
dend3 <- df %>% dist %>% hclust("average") %>% as.dendrogram
dend4 <- df %>% dist %>% hclust("centroid") %>% as.dendrogram
dend_list <- dendlist("Complete" = dend1, "Single" = dend2,
"Average" = dend3, "Centroid" = dend4)
cors <- cor.dendlist(dend_list)
round(cors, 2)## Complete Single Average Centroid
## Complete 1.00 0.46 0.45 0.30
## Single 0.46 1.00 0.23 0.17
## Average 0.45 0.23 1.00 0.31
## Centroid 0.30 0.17 0.31 1.00
Replica de ejemplos capitulo 9
Cargar datos y crear dendrograma
Dendrograma con títulos personalizados
library(factoextra)
fviz_dend(hc, cex = 0.5,
main = "Dendrogram - ward.D2",
xlab = "Objects", ylab = "Distance", sub = "")Dendrograma con colores y rectángulos
fviz_dend(hc, k = 4,
cex = 0.5,
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE,
rect = TRUE,
rect_border = "jco",
rect_fill = TRUE)Cambiar tema del gráfico
fviz_dend(hc, k = 4,
cex = 0.5,
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE,
ggtheme = theme_gray()
)Dendrograma horizontal con rectángulos
fviz_dend(hc, k = 4, cex = 0.4, horiz = TRUE, k_colors = "jco",
rect = TRUE, rect_border = "jco", rect_fill = TRUE)Visualización tipo phylogenic
Visualización phylogenic con layout gem
require("igraph")
fviz_dend(hc, k = 4,
k_colors = "jco",
type = "phylogenic", repel = TRUE,
phylo_layout = "layout.gem")Extraer datos del dendrograma generado
Cortar dendrograma a una altura específica
Crear dendrograma básico
data <- scale(USArrests)
dist.res <- dist(data)
hc <- hclust(dist.res, method = "ward.D2")
dend <- as.dendrogram(hc)
plot(dend)5. Ejemplo de aplicación
Indicación: Presente un ejemplo de aplicación de Análisis de Cluster, con datos de un caso de los disponibles en https://www.kaggle.com/datasets (puede buscar dentro del sitio por la palabra clave “Cluster”.
El DataSet a desarrollar para este ejemplo es el de: Unsupervised Learning on Country Data.
Esta data clasifica los países utilizando factores socioeconómicos y sanitarios que determinan el desarrollo general del país.
El DataFrame está compuesto por 167 observaciones (paises) y 10 variables que representan factores socieconómicos de los paises:
Variables incluidas
country – Nombre del país (única variable no numérica)
child_mort – Tasa de mortalidad infantil (por cada 1,000 nacidos vivos)
exports – Exportaciones (% del PIB)
health – Gasto en salud (% del PIB)
imports – Importaciones (% del PIB)income
Ingreso per cápita (en dólares)
inflation – Tasa de inflación (% anual)
life_expec – Esperanza de vida
total_fer – Tasa total de fertilidad
gdpp – PIB per cápita (en dólares)
Importación de datos
library(dplyr)
library(readr)
Country_data <- read_csv("C:/Users/PC/Downloads/archive (1)/Country-data.csv")
Datos5 <- Country_data %>% select(-country)
head(Datos5, 10)## # A tibble: 10 × 9
## child_mort exports health imports income inflation life_expec total_fer gdpp
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 90.2 10 7.58 44.9 1610 9.44 56.2 5.82 553
## 2 16.6 28 6.55 48.6 9930 4.49 76.3 1.65 4090
## 3 27.3 38.4 4.17 31.4 12900 16.1 76.5 2.89 4460
## 4 119 62.3 2.85 42.9 5900 22.4 60.1 6.16 3530
## 5 10.3 45.5 6.03 58.9 19100 1.44 76.8 2.13 12200
## 6 14.5 18.9 8.1 16 18700 20.9 75.8 2.37 10300
## 7 18.1 20.8 4.4 45.3 6700 7.77 73.3 1.69 3220
## 8 4.8 19.8 8.73 20.9 41400 1.16 82 1.93 51900
## 9 4.3 51.3 11 47.8 43200 0.873 80.5 1.44 46900
## 10 39.2 54.3 5.88 20.7 16000 13.8 69.1 1.92 5840
Normalización de datos
## child_mort exports health imports income inflation
## [1,] 1.28765971 -1.134866649 0.27825140 -0.08220771 -0.80582187 0.156864451
## [2,] -0.53733286 -0.478220167 -0.09672528 0.07062429 -0.37424335 -0.311410892
## [3,] -0.27201464 -0.098824422 -0.96317624 -0.63983800 -0.22018227 0.786907640
## [4,] 2.00178723 0.773056185 -1.44372888 -0.16481961 -0.58328920 1.382894441
## [5,] -0.69354825 0.160186135 -0.28603389 0.49607554 0.10142673 -0.599944185
## [6,] -0.58940465 -0.810191444 0.46756001 -1.27594958 0.08067776 1.240992822
## [7,] -0.50013871 -0.740878760 -0.87944359 -0.06568534 -0.54179126 -0.001119352
## [8,] -0.82992677 -0.777359120 0.69691468 -1.07355044 1.25818167 -0.626432487
## [9,] -0.84232482 0.371772224 1.52331959 0.03757953 1.35155202 -0.653582997
## [10,] 0.02305888 0.481213304 -0.34064215 -1.08181163 -0.05937777 0.569325158
## [11,] -0.60676192 -0.222857646 0.39110846 -0.13177485 0.29854192 -0.773347964
## [12,] -0.73570161 1.035714777 -0.67193222 0.16562797 1.24261994 -0.032337708
## [13,] 0.27597905 -0.915984488 -1.19981201 -1.03637509 -0.76276777 -0.060718032
## [14,] -0.59684348 -0.058696026 0.42023286 0.07475488 -0.09568846 -0.705802793
## [15,] -0.81256951 0.375420260 -0.43893700 0.72738885 -0.04900328 0.692306561
## [16,] -0.83736560 1.287429262 1.41410308 1.14870951 1.24261994 -0.558319710
## [17,] -0.48278145 0.623486708 -0.58819957 0.43824722 -0.48058181 -0.628324509
## [18,] 1.80341848 -0.631437679 -0.98866010 -0.40026351 -0.79492867 -0.652447784
## [19,] 0.10984521 0.050745055 -0.58819957 0.98348572 -0.55631554 -0.169509273
## [20,] 0.20654998 0.003320587 -0.71925938 -0.52005075 -0.60870668 0.094427739
## [21,] -0.77785497 -0.416203555 1.55972509 0.18215035 -0.38513656 -0.603728228
## [22,] 0.35284694 0.090873451 0.54037102 0.18215035 -0.19943330 0.107671890
## [23,] -0.45798535 -1.109330397 0.79885009 -1.44943456 -0.13718640 0.059425339
## [24,] -0.68858903 0.959106021 -1.44736943 -0.78027822 3.29158048 0.843668288
## [25,] -0.68115020 0.331643827 0.01977233 0.25237046 -0.09568846 -0.631162541
## life_expec total_fer gdpp
## [1,] -1.61423717 1.89717646 -0.67714308
## [2,] 0.64592380 -0.85739418 -0.48416709
## [3,] 0.66841296 -0.03828924 -0.46398018
## [4,] -1.17569847 2.12176975 -0.51472026
## [5,] 0.70214671 -0.54032130 -0.04169175
## [6,] 0.58970089 -0.38178486 -0.14535428
## [7,] 0.30858634 -0.83097144 -0.53163362
## [8,] 1.28686497 -0.67243500 2.12430964
## [9,] 1.11819624 -0.99611356 1.85151350
## [10,] -0.16368610 -0.67904068 -0.38868844
## [11,] 0.36480925 -0.71867479 0.82034407
## [12,] 0.61219005 -0.52050424 0.42206170
## [13,] -0.01750653 -0.40820760 -0.66595844
## [14,] 0.69090213 -0.77152027 0.16563332
## [15,] -0.01750653 -0.96308514 -0.37832219
## [16,] 1.06197333 -0.71867479 1.71511542
## [17,] 0.09493928 -0.15719157 -0.47052728
## [18,] -0.98454058 1.59331495 -0.66595844
## [19,] 0.17365136 -0.37517917 -0.58837522
## [20,] 0.11742845 0.16648699 -0.59928706
## [21,] 0.70214671 -1.08198747 -0.45579629
## [22,] -1.51303593 -0.04489492 -0.36086323
## [23,] 0.40978758 -0.75830890 -0.09625097
## [24,] 0.73588045 -0.73188616 1.21862644
## [25,] 0.37605383 -0.91023966 -0.33412921
Validación del Cluster
La validación de clústeres consiste en medir la calidad de los resultados de la agrupación. Por ello, antes de aplicar cualquier algoritmo de agrupación de datos, se debe evaluar la tendencia de estos. (Kassambara, 2017, p. 118)
Metodo Hopkins statistic
## $H
## [1] 0.1470677
El valor obtenidos (0.1470) es mucho menor que 0.5, lo que indica que estos datos sí tienen una fuerte tendencia a formar clusters naturales. Es decir, sí tiene sentido aplicar un análisis de clúster (como K-means o PAM) sobre el dataset presentado.
Desarollo de ejemplo
Ya que se validó el dataset se procede a realizar el Analisis de Cluster, para ello se utilizará el metodo no jerarquico K-means dado que contiene valores continuos, numéricos y sin grandes outliers extremos.
Determinación de K
K es el número optimo de cluster en un conjunto de datos, en este ejemplo utilizaremos el método de la silueta y del codo para Kmeans
Metodo del codo
fviz_nbclust(Datos_normalizados, kmeans, method = "wss") +
labs(subtitle = "Metodo del codo para K-means")Metodo de la silueta
library(NbClust)
fviz_nbclust(Datos_normalizados, kmeans, method = "silhouette") +
labs(subtitle = "Método de la silueta con K-means")
El método del codo muestra una tendencia visual ( quiebre cerca de 4 o
5) y el método de la silueta confirma objetivamente que el número óptimo
de grupos es 5. Es decir, con k = 5, los países son lo suficientemente
distintos entre grupos, pero internamente similares dentro de cada
grupo.
K-means
## K-means clustering with 5 clusters of sizes 47, 86, 3, 1, 30
##
## Cluster means:
## child_mort exports health imports income inflation
## 1 1.3023791 -0.417592913 -0.128560729 -0.13256582 -0.6885538 0.20528209
## 2 -0.4205029 0.003231082 -0.220884976 0.03151135 -0.2098741 -0.03418463
## 3 -0.8464575 4.920873128 -0.008138555 4.53442030 2.4322274 -0.50269428
## 4 2.2745443 -0.576717139 -0.635526719 -1.21812126 -0.6221935 9.10234253
## 5 -0.8261247 0.172103053 0.856613486 -0.29548409 1.4578905 -0.47675466
## life_expec total_fer gdpp
## 1 -1.2754642 1.3383636 -0.6036379
## 2 0.2823054 -0.4519127 -0.3262422
## 3 1.2231457 -1.0357477 2.4334786
## 4 -1.1307201 1.9103878 -0.5801913
## 5 1.1043279 -0.7613916 1.6569189
##
## Clustering vector:
## [1] 1 2 2 1 2 2 2 5 5 2 2 2 2 2 2 5 2 1 2 2 2 1 2 5 2 1 1 2 1 5 2 1 1 2 2 2 1
## [38] 1 1 2 1 2 5 2 5 2 2 2 2 1 1 2 2 5 5 1 1 2 5 1 5 2 2 1 1 2 1 2 5 2 2 2 1 5
## [75] 5 5 2 5 2 2 1 1 5 2 1 2 2 1 1 2 2 3 2 1 1 2 2 1 3 1 2 2 2 2 2 2 1 2 1 2 5
## [112] 5 1 4 5 2 1 2 2 2 2 2 5 5 2 2 1 2 2 1 2 2 1 3 2 5 1 1 5 5 2 2 1 2 5 5 2 1
## [149] 2 1 1 2 2 2 2 1 2 5 5 5 2 2 2 2 2 1 1
##
## Within cluster sum of squares by cluster:
## [1] 196.22502 267.44392 20.87409 0.00000 131.68189
## (between_SS / total_SS = 58.8 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
Tabla resumen de clusters
tabla_clusters <- aggregate(Datos_normalizados, by = list(Cluster = kmean$cluster), mean)
print(tabla_clusters)## Cluster child_mort exports health imports income
## 1 1 1.3023791 -0.417592913 -0.128560729 -0.13256582 -0.6885538
## 2 2 -0.4205029 0.003231082 -0.220884976 0.03151135 -0.2098741
## 3 3 -0.8464575 4.920873128 -0.008138555 4.53442030 2.4322274
## 4 4 2.2745443 -0.576717139 -0.635526719 -1.21812126 -0.6221935
## 5 5 -0.8261247 0.172103053 0.856613486 -0.29548409 1.4578905
## inflation life_expec total_fer gdpp
## 1 0.20528209 -1.2754642 1.3383636 -0.6036379
## 2 -0.03418463 0.2823054 -0.4519127 -0.3262422
## 3 -0.50269428 1.2231457 -1.0357477 2.4334786
## 4 9.10234253 -1.1307201 1.9103878 -0.5801913
## 5 -0.47675466 1.1043279 -0.7613916 1.6569189
Análisis de resultado
Cluster 1: Alta mortalidad infantil (child_mort = 1.3), bajo ingreso y PIB (income = -0.68, gdpp = -0.60), baja esperanza de vida (life_expec = -1.27) Es decir, son países en desarrollo.
Cluster 2: Variables cercanas al promedio, con ligera mejora en salud (life_expec = 0.28). Es decir, países con desarrollo intermedio.
Cluster 3: Muy alto ingreso y PIB (income = 2.43, gdpp = 2.43), alto comercio (exports = 4.92, imports = 4.53), baja mortalidad (child_mort = -0.85). Es decir, paises con economías avanzadas.
Cluster 4: Mortalidad e inflación extremadamente altas (child_mort = 2.27, inflation = 9.10), ingresos bajos. Es decir, países con inestabilidad económica.
Cluster 5: Alta salud y PIB (health = 0.85, gdpp = 1.65), buena esperanza de vida (life_expec = 1.10). Es decir, países en crecimiento sólido.
Adicionalmente, el modelo de K-means logró explicar el 58.8% de la variabilidad total de los datos mediante los 5 clústeres. Es un valor razonablemente bueno para datos socioeconómicos (no se espera un 100% porque las variables tienen mucha dispersión).
Componentes
## [1] 1 2 2 1 2 2 2 5 5 2 2 2 2 2 2 5 2 1 2 2 2 1 2 5 2 1 1 2 1 5 2 1 1 2 2 2 1
## [38] 1 1 2 1 2 5 2 5 2 2 2 2 1 1 2 2 5 5 1 1 2 5 1 5 2 2 1 1 2 1 2 5 2 2 2 1 5
## [75] 5 5 2 5 2 2 1 1 5 2 1 2 2 1 1 2 2 3 2 1 1 2 2 1 3 1 2 2 2 2 2 2 1 2 1 2 5
## [112] 5 1 4 5 2 1 2 2 2 2 2 5 5 2 2 1 2 2 1 2 2 1 3 2 5 1 1 5 5 2 2 1 2 5 5 2 1
## [149] 2 1 1 2 2 2 2 1 2 5 5 5 2 2 2 2 2 1 1
## [1] 47 86 3 1 30
El cluster 1 tiene 47 países
El cluster 2 tiene 86 países
El cluster 3 tiene 3 países
El cluster 4 tiene 1 país (posible outlier)
El cluster 5 tiene 30 países
## child_mort exports health imports income inflation
## 1 1.3023791 -0.417592913 -0.128560729 -0.13256582 -0.6885538 0.20528209
## 2 -0.4205029 0.003231082 -0.220884976 0.03151135 -0.2098741 -0.03418463
## 3 -0.8464575 4.920873128 -0.008138555 4.53442030 2.4322274 -0.50269428
## 4 2.2745443 -0.576717139 -0.635526719 -1.21812126 -0.6221935 9.10234253
## 5 -0.8261247 0.172103053 0.856613486 -0.29548409 1.4578905 -0.47675466
## life_expec total_fer gdpp
## 1 -1.2754642 1.3383636 -0.6036379
## 2 0.2823054 -0.4519127 -0.3262422
## 3 1.2231457 -1.0357477 2.4334786
## 4 -1.1307201 1.9103878 -0.5801913
## 5 1.1043279 -0.7613916 1.6569189
# Resultados del K-means con la data original
df_final <- cbind(Country_data, cluster = kmean$cluster)
head(df_final)## country child_mort exports health imports income inflation
## 1 Afghanistan 90.2 10.0 7.58 44.9 1610 9.44
## 2 Albania 16.6 28.0 6.55 48.6 9930 4.49
## 3 Algeria 27.3 38.4 4.17 31.4 12900 16.10
## 4 Angola 119.0 62.3 2.85 42.9 5900 22.40
## 5 Antigua and Barbuda 10.3 45.5 6.03 58.9 19100 1.44
## 6 Argentina 14.5 18.9 8.10 16.0 18700 20.90
## life_expec total_fer gdpp cluster
## 1 56.2 5.82 553 1
## 2 76.3 1.65 4090 2
## 3 76.5 2.89 4460 2
## 4 60.1 6.16 3530 1
## 5 76.8 2.13 12200 2
## 6 75.8 2.37 10300 2
Grafico de Clusters
# Visualize k-means clusters
country_names <- Country_data$country
rownames(Datos_normalizados) <- country_names
fviz_cluster(kmean,
data = Datos_normalizados,
palette = c("#2E9FDF", "#F164FA", "#E7B800", "#FC4E07", "#99DE99"),
ellipse.type = "euclid",
star.plot = TRUE,
repel = TRUE,
ggtheme = theme_minimal())