Análisis de Clúster (Conglomerados)

UNIVERSIDAD DE EL SALVADOR

FACULTAD DE CIENCIAS ECONÓMICAS

ESCUELA DE ECONOMÍA

MÉTODOS PARA EL ANÁLISIS ECONÓMICO

TEMA DE INVESTIGACIÓN:

Análisis de Clúster (Conglomerados)

DOCENTE:

MSF. Carlos Ademir Pérez Alas.

Grupo teórico

GT-03

Integrantes: Carnet: Participación
Lopez Coto Ezequiel Benjamin LC22057 100%
Méndez Benítez Carlos Mauricio MB22006 100%
Martínez Guardado Erick Jesé MG22058 100%

CIUDAD UNIVERSITARIA, 24 DE NOVIEMBRE DE 2024

1. Explique en qué consiste el análisis de conglomerados

También conocido como análisis de clúster, es una técnica utilizada para agrupar una serie de datos u objetos que son similares entre sí, es decir, son homogéneos. Estos datos u objetos agrupados de forma homogénea son los grupos llamados conglomerados o clusters, estos tipos de conglomerados o clusters permiten una interpretación de manera más sencilla de los datos u objetos.

2. Elabore un cuadro comparativo, que incluya los siguientes elementos:

Resumen del Análisis de Clúster

Análisis de Clúster

Técnicas disponibles

Ventajas

Desventajas

Jerárquico:

No requiere que se pre especifique el número de clústeres, es decir genera un dendrograma que muestra las relaciones jerárquicas entre las observaciones.

  • AGLOMERATIVO (DE ABAJO HACIA ARRIBA)

  • Método de Ward.

  • DIVISIVO (DE ARRIBA HACIA ABAJO).

Bueno para identificar clústeres pequeños. Permite visualizar la estructura de los datos a diferentes niveles de granularidad.

  • No requiere predefinir el número de clústeres

  • Visualización intuitiva

  • Identificación de clústeres pequeños

  • Flexibilidad en la elección del método de enlace

Puede ser computacionalmente costoso para conjuntos de datos grandes. La elección del método de enlace puede influir en los resultados.

  • Costo computacional.

  • Asignación irrevocable.

  • Sensibilidad al ruido y a los valores atípicos

No jerárquico:

Requieren que el usuario defina el número de clústeres de antemano, es decir divide los datos en un número predefinido de clústeres.

 

 

  • K-MEANS

  • K-MEDOIDS (PAM)

 

  • CLARA.

Generalmente más eficiente computacionalmente que los métodos jerárquicos, especialmente para conjuntos de datos grandes.

  • Eficiencia computacional

  • Escalabilidad y Simplicidad (K-means)

Sensible a la elección del número de clústeres. Puede tener dificultades para encontrar clústeres con formas no esféricas.

  • Necesidad de especificar el número de clústeres

  •  Sensibilidad a la inicialización(K-means)

  • Dificultad para encontrar clústeres con formas no convexas (K-means)

Fuente: Elaboración propia con base en (Kassambara, A. (2017). Practical Guide to Cluster Analysis in R: Unsupervised Machine Learning (Multivariate Analysis) (1st ed.). STHDA,) y Joaquin, A. M., & Ezequiel, U. J. (2017). Análisis multivariante aplicado con R. 2a ed. Ediciones Paraninfo, S.A. y Landa Baella, María del Pilar, “DESARROLLO DE ANÁLISIS CLÚSTER EN R”

3. Describa las técnicas disponibles para realizar el análisis de clúster, tanto jerárquicas como no jerárquicas, presentadas en el cuadro anterior, incluya una explicación de la librería y sintaxis para implementarla en R

Técnicas jerárquicas

Aglomerativo (AGNES)

El algoritmo AGNES (Anidación Aglomerativa, Agglomerative Nesting,), dentro de las técnicas jerárquicas es el más común, este se utiliza para agrupar objetos en grupos según similitud. en este tipo de técnica se inicia tratando cada objeto como un grupo de un solo grupo, luego se fusionan pares de grupos de manera sucesiva hasta que todos los grupos se han fusionado en un gran grupo que contiene todos los objetos.

Esta técnica funciona de manera ascendente, es decir, cada objeto se considera inicialmente como un grupo de un solo elemento. En cada paso, los grupos dos grupos más similares se combinan en un nuevo grupo más grande(nodos), esto se repite hasta que todos los grupos sean miembro de un solo grupo grande. Este tipo de agrupación aglomerativa es buena para identificar agrupaciones pequeñas.

La función agnes() en R, que forma parte del paquete [cluster]

#agnes(x, diss = inherits(x, "dist"), metric = "euclidean", stand = FALSE, method = "average", par.method, keep.diss = n < 100, keep.data = !diss, trace.lev = 0)

Sintaxis de agnes():

  • x: Este es el conjunto de datos que se va a analizar.

  • diss: Indica si x ya es un objeto de distancia (TRUE) o si es necesario calcular las distancias (FALSE).

  • metric: Especifica la métrica de distancia que se utilizará si x no es una matriz de distancias.

  • stand: Indica si las variables en los datos deben ser estandarizadas antes de calcular las distancias.

  • method: Especifica el método de agrupamiento jerárquico que se utilizará.

  • par.method: Argumento opcional para ajustar parámetros específicos del método elegido, este usualmente no se utiliza

  • keep.diss: Determina si se debe guardar la matriz de disimilitudes calculada en el objeto de salida.

  • keep.data: Indica si los datos originales deben almacenarse en el objeto de salida.

  • trace.lev: Controla el nivel de detalle de los mensajes que la función imprime mientras ejecuta el algoritmo.

Divisivo (DIANA)

El algoritmo de DIANA construye una jerarquía de agrupaciones, comenzando con un gran grupo que contiene todas las n observaciones. Los grupos se dividen hasta que cada uno contiene solo una observación.

Este proporciona (a) el coeficiente divisorio que mide la cantidad de estructura de agrupamiento encontrada; y (b) el banner, una novedosa visualización gráfica.

En cada etapa, se selecciona el grupo con el diámetro más grande. (El diámetro de un grupo es la mayor disimilitud entre dos de sus observaciones). Para dividir el grupo seleccionado, el algoritmo primero busca su observación más dispar (es decir, la que tiene la mayor disimilitud promedio con las otras observaciones del grupo seleccionado). Esta observación inicia el “grupo fragmentado”. En los pasos posteriores, el algoritmo reasigna las observaciones que están más cerca del “grupo fragmentado” que del “grupo anterior”. El resultado es una división del grupo seleccionado en dos nuevos grupos.

La función diana() en R, que forma parte del paquete [cluster]

#diana(x, diss = inherits(x, "dist"), metric = "euclidean", stand = FALSE, stop.at.k = FALSE, keep.diss = n < 100, keep.data = !diss, trace.lev = 0)

Sintaxis de diana():

  • x: Este es el conjunto de datos que se va a analizar. Puede ser un marco de datos o una matriz de disimilitud.
  • diss: Un valor lógico que indica si x es una matriz de disimilitud. Si TRUE, se asume que x ya contiene las distancias entre las observaciones.
  • metric: Especifica la métrica a utilizar para calcular las distancias. Por defecto es “euclidean”, pero puede cambiarse a otras métricas como “manhattan”.
  • stand: Un valor lógico que indica si los datos deben ser estandarizados antes del análisis. La estandarización puede ser importante para evitar que variables con diferentes escalas influyan desproporcionadamente en el agrupamiento.
  • stop.at.k: Indica si el algoritmo debe detenerse después de crear k grupos. Esto puede ser útil si solo se desea un número específico de agrupaciones.
  • keep.diss: Un valor lógico que determina si la matriz de disimilitud debe conservarse en el resultado. Esto puede ser útil para conjuntos de datos más pequeños.
  • keep.data: Indica si los datos originales deben conservarse en el resultado. Esto es relevante cuando se trabaja con matrices de disimilitud.
  • trace.lev: Un parámetro que controla el nivel de detalle del seguimiento durante la ejecución del algoritmo. Puede ser útil para depuración o análisis detallado del proceso.

Técnicas no jerárquicas

K-Means

El algoritmo de agrupamiento de k-medias (k-means, MacQueen, 1967) genera agrupaciones con un número (k) dado por el investigador, donde las agrupaciones se representan con su centroide, que no es más que el promedio de los objetos dentro de cada grupo.

El objetivo es minimizar la distancia entre objetos dentro de cada grupo y maximizar la distancia entre los objetos de diferentes grupos.

Sintetizando Kassambara (2017), el algoritmo procede así:

  1. Establecer el número de agrupaciones (k)
  2. Elegir aleatoriamente k objetos del conjunto de datos como primeros centroides
  3. Asignar los objetos a las agrupaciones con el centroide más cercano
  4. Actualizar los centroides como el promedio dentro de cada agrupación
  5. Repetir desde el paso 3 hasta que la asignación de objetos deje de cambiar o se alcance el máximo de iteraciones

La función R estándar para agrupación de k-medias es kmeans de la librería [stats].

#kmeans(x, centers, iter.max = 10, nstart = 1)

Sintaxis:

  • x: conjunto de datos numérico (matriz, vector o data frame numéricos)

  • centers: número de agrupaciones para asignación aleatoria o un conjunto de centroides distintos

  • iter.max: número máximo de iteraciones (10 por default)

  • nstart: número de conjuntos aleatorios iniciales cuando centers es un número (1 por default)

K-Medoids (PAM)

El algoritmo k-medoides o PAM (Particionamiento Alrededor de Medoides, Partitioning Around Medoids, Kaufman & Rousseeuw, 1990) también genera agrupaciones con un número (k) dado por el investigador, pero ahora las agrupaciones se representan con un medoide. Los medoides siempre serán puntos dentro del conjunto de datos.

Este método busca ser más robusto que el de k-medias respecto a la sensibilidad de los outliers.

Según Javatpoint (s.f.), el algoritmo procede de la siguiente manera:

  1. Seleccione k puntos aleatorios de los datos y asígnelos a k grupos. Estos son los medoides iniciales.
  2. Para todos los puntos de datos restantes, calcule la distancia desde cada medoide y asígnela al grupo con el medoide más cercano.
  3. Calcule el costo total (suma de todas las distancias desde todos los puntos de datos hasta los medoides)
  4. Seleccione un punto aleatorio como el nuevo medoide e intercámbielo con el medoide anterior. Repita los pasos 2 y 3.
  5. Si el costo total del nuevo medoide es menor que el del medoide anterior, haga que el nuevo medoide sea permanente y repita el paso 4.
  6. Si el costo total del nuevo medoide es mayor que el costo del medoide anterior, deshaga el intercambio y repita el paso 4.
  7. Las repeticiones deben continuar hasta que no se encuentre ningún cambio con los nuevos medoides para clasificar los puntos de datos.

Las funciones pam() de [cluster] y pamk() de [fpc] pueden utilizarse para calcular PAM.

#pam(x, k, diss, metric = "euclidean", stand = FALSE)

Sintaxis de pam():

  • x: conjunto de observaciones (matriz o data frame numéricos) o matriz de distancias

  • k: número de agrupaciones

  • diss: valor lógico para tratar a x como matriz de distancias si es TRUE

  • metric: medida para calcular las distancias, puede ser “euclidean” o “manhattan”

  • stand: valor lógico para estandarizar columnas antes de calcular las distancias

#pamk(data,krange=2:10, criterion="asw", usepam=TRUE, diss=inherits(data, "dist"))

Sintaxis de pamk():

  • data: conjunto de observaciones (matriz o data frame numéricos) o matriz de distancias
  • krange: vector de enteros. Número de agrupaciones a ser comparadas con el criterio de la anchura promedio de silueta
  • criterion: criterio para calcular el número óptimo de agrupaciones, puede ser “asw”, “multiasw” o “ch”
  • usepam: se aplica PAM si es TRUE, se aplica CLARA si es FALSE
  • diss: valor lógico para tratar a data como matriz de distancias si es TRUE

Esta última opción tiene la ventaja de que puede escoger k automáticamente usando el criterio seleccionado

CLARA

El algoritmo CLARA (Agrupamiento de Aplicaciones Grandes, Clustering Large Applications, Kaufman and Rousseeuw, 1990) es una modificación de PAM con el objetivo de reducir el costo computacional a cambio de ser menos preciso. Es especialmente útil al tratar con conjuntos grandes de datos.

Según Kassambara (2017), en vez de encontrar los medoides del conjunto de datos completo, se considera una muestra pequeña de los datos con tamaño fijo para aplicársele PAM y así generar un conjunto óptimo de medoides. Este proceso se repite un número determinado de veces para minimizar el sesgo muestral y al final se quedará el conjunto de medoides con el coste mínimo.

El algoritmo procede así:

  1. Seleccione un subconjunto aleatorio del conjunto de datos original que contenga una cantidad representativa de puntos. Este subconjunto es mucho más pequeño que el conjunto de datos completo, lo que reduce el costo computacional.
  2. Ejecute el algoritmo PAM en este subconjunto seleccionado: 2.1. Seleccione k puntos como medoides iniciales. 2.2. Asigne cada punto del subconjunto al medoide más cercano. 2.3. Calcule el costo total (suma de las distancias entre los puntos del subconjunto y sus medoides).
  3. Asigne todos los puntos del conjunto de datos original (no solo los del subconjunto) al medoide más cercano encontrado en el paso 2 y calcule el costo total considerando todos los datos.
  4. Repita los pasos 1, 2 y 3 varias veces con diferentes subconjuntos aleatorios. Esto permite explorar distintas configuraciones de medoides y reduce la posibilidad de quedar atrapado en un óptimo local.
  5. Compare los costos totales obtenidos para cada subconjunto y seleccione como resultado final los medoides que correspondan al menor costo total.
  6. Asigne cada punto del conjunto de datos completo al medoide más cercano del modelo final.
  7. Las repeticiones terminan cuando se ha alcanzado el número máximo de subconjuntos analizados o cuando los resultados convergen.

La librería [cluster] contiene a la función clara(), la cual resulta útil para estimar CLARA.

#clara(x, k, metric = "euclidean", stand = FALSE, samples = 5, pamLike = FALSE)
  • x: matriz o data frame con los datos a agrupar. Deben ser numéricos o convertibles a números

  • k: número de agrupaciones deseadas

  • metric: medida de distancia utilizada para calcular la similitud entre puntos, puede ser “euclidean” o “manhattan”

  • samples: número de muestras aleatorias a tomar del conjunto de datos

  • sampsize: tamaño de cada subconjunto aleatorio

  • pamLike: Si es TRUE, el algoritmo se comporta como PAM en cada subconjunto; debe ser siempre TRUE

4. Del texto: Kassambara, A. (2017). Practical Guide to Cluster Analysis in R: Unsupervised Machine Learning (Multivariate Analysis) (1st ed.). STHDA, desarrolle los ejemplos presentados en los capítulos: 4,5,6,7,8,9

Chapter 4 K-Means Clustering

data("USArrests") # Loading the data set
df <- scale(USArrests) # Scaling the data
# View the firt 3 rows of the data
head(df, n = 3)
##             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

Estimación del número óptimo de clústeres.

library(factoextra)
fviz_nbclust(df, kmeans, method = "wss") +
geom_vline(xintercept = 4, linetype = 2)

# Set seed for reproducibility
set.seed(123)

# Perform k-means clustering with 4 clusters and 25 random starts
km.res <- kmeans(df, centers = 4, nstart = 25)

# Print the results
print(km.res)
## 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"

CÁLCULO DE LA AGRUPACIÓN DE K-MEANS EN R

library(kableExtra)
dd <- cbind(USArrests, cluster = km.res$cluster)
head(dd) %>% kable() %>% kable_minimal()
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

Resultados de la función kmeans()

# Número de clúster para cada una de las observaciones
km.res$cluster
##        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
head(km.res$cluster, 4)
##  Alabama   Alaska  Arizona Arkansas 
##        1        4        4        1
# Tamaño del clúster
km.res$size
## [1]  8 13 16 13
# Media del Clúster.
km.res$centers
##       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

Visualización de clústeres de k-medias

fviz_cluster(km.res, data = df,
palette = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
ellipse.type = "euclid", # Concentration ellipse
star.plot = TRUE, # Add segments from centroids to items
repel = TRUE, # Avoid label overplotting (slow)
ggtheme = theme_minimal()
)

Chapter 5 K-Medoids

Estimación del número óptimo de conglomerados

library(cluster)
library(factoextra)
fviz_nbclust(df, pam, method = "silhouette")+
theme_classic()

Cálculo de la agrupación PAM.

A partir del gráfico, el número de conglomerados sugerido es 2. Y por eso clasificaremos las observaciones en 2 conglomerados

pam.res <- pam(df, 2)
print(pam.res)
## 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"
#Si desea añadir las clasificaciones de puntos a los datos originales, utilice esto:

dd <- cbind(USArrests, cluster = pam.res$cluster)
head(dd, n = 3)
##         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

Acceso a los resultados de la función pam()

#medoides: Objetos que representan conglomerados
# Cluster medoids: New Mexico, Nebraska
pam.res$medoids
##                Murder    Assault   UrbanPop       Rape
## New Mexico  0.8292944  1.3708088  0.3081225  1.1603196
## Nebraska   -0.8008247 -0.8250772 -0.2445636 -0.5052109
# Números de Cluster
head(pam.res$clustering)
##    Alabama     Alaska    Arizona   Arkansas California   Colorado 
##          1          1          1          2          1          1

Visualización de clústeres PAM

fviz_cluster(pam.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
repel = TRUE, # Avoid label overplotting (slow)
ggtheme = theme_classic()
)

Chapter 6 CLARA - Clustering Large Applications

Formato y preparación de los datos

#Generar 500 objetos, divididos en 2 clústeres.
df <- rbind(cbind(rnorm(200,0,8), rnorm(200,0,8)),
cbind(rnorm(300,50,8), rnorm(300,50,8)))
# Especificar nombres de columnas y filas 
colnames(df) <- c("x", "y")
rownames(df) <- paste0("S", 1:nrow(df))
# Previewing the data
head(df, nrow = 6)
##             x         y
## S1 -4.4838052 17.590483
## S2 -1.8414199 10.499304
## S3 12.4696665 -2.121160
## S4  0.5640671  4.345552
## S5  1.0343019 -3.314720
## S6 13.7205199 -3.809975

Estimación del número óptimo de clústeres

library(cluster)
library(factoextra)
fviz_nbclust(df, clara, method = "silhouette")+
theme_classic()

A partir del gráfico, el número de conglomerados sugerido es 2,clasificaremos las observaciones en 2 conglomerados.

Calculando CLARA

# Compute CLARA
clara.res <- clara(df, 2, samples = 50, pamLike = TRUE)
# Print components of clara.res
print(clara.res)
## Call:     clara(x = df, k = 2, samples = 50, pamLike = TRUE) 
## Medoids:
##               x          y
## S117  0.8454096 -0.8453707
## S464 49.7728396 50.3738682
## Objective function:   9.922068
## 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] S5   S13  S21  S23  S32  S62  S66  S67  S102 S110 S114 S117 S119 S125 S174
## [16] S195 S198 S226 S235 S236 S260 S264 S266 S282 S290 S293 S297 S307 S318 S319
## [31] S335 S339 S341 S358 S360 S388 S390 S393 S401 S415 S433 S464 S474 S490
## 
## Available components:
##  [1] "sample"     "medoids"    "i.med"      "clustering" "objective" 
##  [6] "clusinfo"   "diss"       "call"       "silinfo"    "data"

Si desea añadir las clasificaciones de puntos a los datos originales

dd <- cbind(df, cluster = clara.res$cluster)
head(dd, n = 4)
##             x         y cluster
## S1 -4.4838052 17.590483       1
## S2 -1.8414199 10.499304       1
## S3 12.4696665 -2.121160       1
## S4  0.5640671  4.345552       1
# Medoids
clara.res$medoids
##               x          y
## S117  0.8454096 -0.8453707
## S464 49.7728396 50.3738682
# Agrupamiento
head(clara.res$clustering, 10)
##  S1  S2  S3  S4  S5  S6  S7  S8  S9 S10 
##   1   1   1   1   1   1   1   1   1   1

Los medoides son S121, S455

Visualización de clusters de CLARA

fviz_cluster(clara.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
geom = "point", pointsize = 1,
ggtheme = theme_classic()
)

Chapter 7 Agglomerative Clustering

Estructura y preparación de datos

# Load the data
data("USArrests")

# Standardize the data
df <- scale(USArrests)

# Show the first 6 rows
head(df, nrow = 6)
##                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
# Compute the dissimilarity matrix
# df = the standardized data
res.dist <- dist(df, method = "euclidean")

# Distance matrix
as.matrix(res.dist)[1:6, 1:6]
##             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
# Linkage
res.hc <- hclust(d = res.dist, method = "ward.D2")

# Dendogram
# cex: label size
library("factoextra")
fviz_dend(res.hc, cex = 0.5)

Verificar el árbol de conglomerados

# Compute cophentic distance
res.coph <- cophenetic(res.hc)

# Correlation between cophenetic distance and
# the original distance
cor(res.dist, res.coph)
## [1] 0.6975266
res.hc2 <- hclust(res.dist, method = "average")

cor(res.dist, cophenetic(res.hc2))
## [1] 0.7180382

Cortar el dendograma en diferentes grupos

# Cut tree into 4 groups
grp <- cutree(res.hc, k = 4)
head(grp, n = 4)
##  Alabama   Alaska  Arizona Arkansas 
##        1        2        2        3
# Number of members in each cluster
table(grp)
## grp
##  1  2  3  4 
##  7 12 19 12
# Get the names for the members of cluster 1
rownames(df)[grp == 1]
## [1] "Alabama"        "Georgia"        "Louisiana"      "Mississippi"   
## [5] "North Carolina" "South Carolina" "Tennessee"
# Cut in 4 groups and color by groups
fviz_dend(res.hc, k = 4, # Cut in four groups
          cex = 0.5, # label size
          k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
          color_labels_by_k = TRUE, # color labels by groups
          rect = TRUE # Add rectangle around groups
          )

fviz_cluster(list(data = df, cluster = grp),
             palette = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
             ellipse.type = "convex", # Concentration ellipse
             repel = TRUE, # Avoid label overplotting (slow)
             show.clust.cent = FALSE, ggtheme = theme_minimal())

Paquete de clúster de R

library("cluster")
# Agglomerative Nesting (Hierarchical Clustering)
res.agnes <- agnes(x = USArrests, # data matrix
                   stand = TRUE, # Standardize the data
                   metric = "euclidean", # metric for distance matrix
                   method = "ward" # Linkage method
                   )

# DIvisive ANAlysis Clustering
res.diana <- diana(x = USArrests, # data matrix
                   stand = TRUE, # standardize the data
                   metric = "euclidean" # metric for distance matrix
                   )

fviz_dend(res.agnes, cex = 0.6, k = 4)

fviz_dend(res.diana, cex = 0.6, k = 4)

Chapter 8 Comparing Dendrograms

Preparación de datos

df <- scale(USArrests)

# Subset containing 10 rows
set.seed(123)
ss <- sample(1:50, 10)
df <- df[ss,]

Comparando dendogramas

library(dendextend)

# Compute distance matrix
res.dist <- dist(df, method = "euclidean")

# Compute 2 hierarchical clusterings
hc1 <- hclust(res.dist, method = "average")
hc2 <- hclust(res.dist, method = "ward.D2")

# Create two dendrograms
dend1 <- as.dendrogram (hc1)
dend2 <- as.dendrogram (hc2)

# Create a list to hold dendrograms
dend_list <- dendlist(dend1, dend2)

tanglegram(dend1, dend2)

tanglegram(dend1, dend2,
           highlight_distinct_edges = FALSE, # Turn-off dashed lines
           common_subtrees_color_lines = FALSE, # Turn-off line colors
           common_subtrees_color_branches = TRUE, # Color common branches
           main = paste("entanglement =",
                        round(entanglement(dend_list), 2))
           )

# Cophenetic correlation matrix
cor.dendlist(dend_list, method = "cophenetic")
##           [,1]      [,2]
## [1,] 1.0000000 0.9925544
## [2,] 0.9925544 1.0000000
# Baker correlation matrix
cor.dendlist(dend_list, method = "baker")
##           [,1]      [,2]
## [1,] 1.0000000 0.9895528
## [2,] 0.9895528 1.0000000
# Cophenetic correlation coefficient
cor_cophenetic(dend1, dend2)
## [1] 0.9925544
# Baker correlation coefficient
cor_bakers_gamma(dend1, dend2)
## [1] 0.9895528
# Create multiple dendrograms by chaining
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()

# Compute correlation matrix
dend_list <- dendlist("Complete" = dend1, "Single" = dend2,
"Average" = dend3, "Centroid" = dend4)

cors <- cor.dendlist(dend_list)
# Print correlation matrix
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
# Visualize the correlation matrix using corrplot package
library(corrplot)
corrplot(cors, "pie", "lower")

Chapter 9 Visualizing Dendrograms

# Load data
data(USArrests)

# Compute distances and hierarchical clustering
dd <- dist(scale(USArrests), method = "euclidean")
hc <- hclust(dd, method = "ward.D2")

Visualizando dendogramas

library(factoextra)
fviz_dend(hc, cex = 0.5)

fviz_dend(hc, cex = 0.5,
          main = "Dendrogram - ward.D2",
          xlab = "Objects", ylab = "Distance", sub = "")

fviz_dend(hc, cex = 0.5, horiz = TRUE)

fviz_dend(hc, k = 4, # Cut in four groups
          cex = 0.5, # label size
          k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
          color_labels_by_k = TRUE, # color labels by groups
          rect = TRUE, # Add rectangle around groups
          rect_fill = TRUE)

fviz_dend(hc, k = 4, # Cut in four groups
          cex = 0.5, # label size
          k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
          color_labels_by_k = TRUE, # color labels by groups
          ggtheme = theme_gray() # Change theme
          )

fviz_dend(hc, cex = 0.5, k = 4, # Cut in four groups
          k_colors = "jco")

fviz_dend(hc, k = 4, cex = 0.4, horiz = TRUE, k_colors = "jco",
          rect = TRUE, rect_border = "jco", rect_fill = TRUE)

fviz_dend(hc, cex = 0.5, k = 4,
          k_colors = "jco", type = "circular") 

require("igraph")
fviz_dend(hc, k = 4, k_colors = "jco",
          type = "phylogenic", repel = TRUE)

fviz_dend(hc, k = 4, # Cut in four groups
          k_colors = "jco",
          type = "phylogenic", repel = TRUE,
          phylo_layout = "layout.gem")

Caso de dendograma con conjuntos grandes de datos

fviz_dend(hc, xlim = c(1, 20), ylim = c(1, 8))

# Create a plot of the whole dendrogram,
# and extract the dendrogram data
dend_plot <- fviz_dend(hc, k = 4, # Cut in four groups
                       cex = 0.5, # label size
                       k_colors = "jco"
                       )

dend_data <- attr(dend_plot, "dendrogram") # Extract dendrogram data

# Cut the dendrogram at height h = 10
dend_cuts <- cut(dend_data, h = 10)
# Visualize the truncated version containing
# two branches
fviz_dend(dend_cuts$upper) 

# Plot the whole dendogram
print(dend_plot)

# Plot subtree 1
fviz_dend(dend_cuts$lower[[1]], main = "Subtree 1")

# Plot subtree 2
fviz_dend(dend_cuts$lower[[2]], main = "Subtree 2")

fviz_dend(dend_cuts$lower[[2]], type = "circular") 

pdf("dendrogram.pdf", width=30, height=15) # Open a PDF
p <- fviz_dend(hc, k = 4, cex = 1, k_colors = "jco" ) # Do plotting
print(p)
dev.off() # Close the PDF
## png 
##   2

Manipulando dendogramas usando dendextend

data <- scale(USArrests)
dist.res <- dist(data)
hc <- hclust(dist.res, method = "ward.D2")
dend <- as.dendrogram(hc)
plot(dend)

library(dendextend)
dend <- USArrests[1:5,] |> # data
  scale() |>  # Scale the data
  dist() |>  # calculate a distance matrix,
  hclust(method = "ward.D2") |> # Hierarchical clustering
  as.dendrogram() # Turn the object into a dendrogram.
plot(dend)

library(dendextend)
# 1. Create a customized dendrogram
mycols <- c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07")
dend <- as.dendrogram(hc) %>%
set("branches_lwd", 1) %>% # Branches line width
set("branches_k_color", mycols, k = 4) %>% # Color branches by groups
set("labels_colors", mycols, k = 4) %>% # Color labels by groups
set("labels_cex", 0.5) # Change label size
# 2. Create plot
fviz_dend(dend)

Bibliografía

Allaire, JJ, Yihui Xie, Christophe Dervieux, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, et al. 2024. Rmarkdown: Dynamic Documents for r. https://github.com/rstudio/rmarkdown.
Barnier, Julien. 2022. Rmdformats: HTML Output Formats and Templates for Rmarkdown Documents. https://github.com/juba/rmdformats.
Csardi, Gabor, and Tamas Nepusz. 2006. “The Igraph Software Package for Complex Network Research.” InterJournal Complex Systems: 1695. https://igraph.org.
Csárdi, Gábor, Tamás Nepusz, Vincent Traag, Szabolcs Horvát, Fabio Zanini, Daniel Noom, and Kirill Müller. 2024. Igraph: Network Analysis and Visualization. https://r.igraph.org/.
Galili, Tal. 2015. “Dendextend: An r Package for Visualizing, Adjusting, and Comparing Trees of Hierarchical Clustering.” Bioinformatics. https://doi.org/10.1093/bioinformatics/btv428.
Galili, Tal, and Gregory Jefferis. 2024. Dendextend: Extending Dendrogram Functionality in r. https://talgalili.github.io/dendextend/.
Hadi, Ali S, L Kaufman, and P J Rousseeuw. 1992. “Finding Groups in Data: An Introduction to Cluster Analysis.” Technometrics 34 (1): 111.
Hennig, Christian. 2024. Fpc: Flexible Procedures for Clustering. https://www.unibo.it/sitoweb/christian.hennig/en/.
Kassambara, Alboukadel. 2017. Practical Guide to Cluster Analysis in r: Unsupervised Machine Learning (Multivariate Analysis) (1st Ed.). STHDA.
Kassambara, Alboukadel, and Fabian Mundt. 2020. Factoextra: Extract and Visualize the Results of Multivariate Data Analyses. http://www.sthda.com/english/rpkgs/factoextra.
K-Medoids Clustering-Theoretical Explanation.” n.d. https://www.javatpoint.com/k-medoids-clustering-theoretical-explanation.
Maechler, Martin, Peter Rousseeuw, Anja Struyf, and Mia Hubert. 2023. Cluster: "Finding Groups in Data": Cluster Analysis Extended Rousseeuw Et Al. https://svn.r-project.org/R-packages/trunk/cluster/.
R Core Team. 2024. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Wei, Taiyun, and Viliam Simko. 2024a. Corrplot: Visualization of a Correlation Matrix. https://github.com/taiyun/corrplot.
———. 2024b. R Package ’Corrplot’: Visualization of a Correlation Matrix. https://github.com/taiyun/corrplot.
Xie, Yihui. 2014. “Knitr: A Comprehensive Tool for Reproducible Research in R.” In Implementing Reproducible Computational Research, edited by Victoria Stodden, Friedrich Leisch, and Roger D. Peng. Chapman; Hall/CRC.
———. 2015. Dynamic Documents with R and Knitr. 2nd ed. Boca Raton, Florida: Chapman; Hall/CRC. https://yihui.org/knitr/.
———. 2024. Knitr: A General-Purpose Package for Dynamic Report Generation in r. https://yihui.org/knitr/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown.
Xie, Yihui, Christophe Dervieux, and Emily Riederer. 2020. R Markdown Cookbook. Boca Raton, Florida: Chapman; Hall/CRC. https://bookdown.org/yihui/rmarkdown-cookbook.
Zhu, Hao. 2024. kableExtra: Construct Complex Table with Kable and Pipe Syntax. http://haozhu233.github.io/kableExtra/.