Actividad Grupal 02

UNIVERSIDAD DE EL SALVADOR

FACULTAD DE CIENCIAS ECONÓMICAS

ESCUELA DE ECONOMÍA

CICLO II-2023

ANÁLISIS DE CLÚSTER (CONGLOMERADOS)

MÉTODOS PARA EL ANÁLISIS ECONÓMICO

DOCENTE:

CARLOS ADEMIR PÉREZ ALAS

PRESENTADO POR:

INTEGRANTES CARNET
ALEMAN MENJIVAR, MEYBELIN NALLELY AM20071
ASCENCIO ORELLANA, FERNANDO JAVIER AO21017
FLORES GARCIA, JAZMIN GUADALUPE FG20019

GRUPO TEÓRICO:

03

GRUPO DE TRABAJO:

08

EL SALVADOR, SAN SALVADOR, CIUDAD UNIVERSITARIA, 07 DE ENERO DEL 2024

1. Explique en que consiste el análisis de conglomerados.

El Análisis Cluster, también conocido como Análisis de Conglomerados, es una técnica estadística multivariante que busca agrupar elementos (o variables) y que trata de lograr la máxima homogeneidad en cada grupo y la mayor diferencia entre grupos.

El Análisis Cluster tiene una gran importancia en aplicación en muchas áreas de investigación. Pero, con los beneficios del Análisis Cluster existen algunas desventajas. El Análisis de Cluster es una técnica descriptiva, teórica y no inferencial. Este Análisis no tiene bases estadísticas para deducir inferencias estadísticas sobre una población a partir de una muestra, es un método que se basa en criterios geométricos y es utilizado fundamentalmente como una técnica exploratoria, descriptiva pero no explicativa.

Finalmente, el análisis cluster depende en su totalidad, de las variables que se utilizan, de la adición o destrucción de variables relevantes que pueden tener un impacto significativo sobre la solución resultante.

2. Cuadro comparativo.

library(kableExtra)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.2
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
text_tbl <- data.frame(
  Analálisis_Cluster = c("Jerárquico: Prentende encontrar grupos discretos según la similitud de sus elementos. Estos grupos se organizan de forma jerárquica y pueden visualizarse a través de un dendrograma. Por lo tanto, en este tipo de análisis no se requiere determinar el número de clústeres de manera previa, estos métodos se dividen en aglomerativo y divisivo.","No Jerárquico: Se conoce de primeras el número k de grupos que desea, y las observaciones son entonces asignadas a cada uno de esos k conglomerados, es por ello que se maximiza la homogeneidad de los sujetos asignados a un mismo grupo y la heterogeneidad entre los distintos conglomerados."),
      
      Técnicas_Disponibles = c(
      "Método de vinculación Simple;  
      Método de vinculación Completo;  
      Método del promedio entre grupos;  
      Método Ward;  
      Método centroide. ",
    "
k-medias;
Clara;
k-medoides.
    "
    ),
      
      Ventajas = c(
      "Es un algoritmo que ofrece ventajas notables, como la generación de una estructura ilustrativa para determinar el número de conglomerados a través del dendrograma. Su implementación es fácil y accesible, siendo comparativamente más confiable y rápido que la agrupación jerárquica. Destaca en situaciones de error y puede ser más eficiente computacionalmente, especialmente con un valor pequeño de K. Por tanto, se considera que K-Means se presenta como una técnica versátil y estable.", "Maximiza la homogeneidad asignados a un mismo grupo y la heterogeneidad entre los distintos conglomerados. Además permite al investigador elegir la cantidad de grupos deseados después de la ejecución del algoritmo."
      ),
      
      Desventajas = c(
      "La irreversibilidad de decisiones incorrectas, ya que no se pueden deshacer pasos anteriores. La complejidad temporal puede resultar en cálculos prolongados, limitando su eficiencia. Además, la necesidad de una gran cantidad de cálculos puede restringir la aplicabilidad en conjuntos de datos extensos, y la imposibilidad de modificar una mala partición una vez realizada presenta un desafío adicional en términos de flexibilidad.","Este enfoque requerirá de suministrar los centroides iniciales (valores medios de las variables que caracterizan las observaciones en cada uno de esos grupos, se le conocen de igual manera como semillas) y estos rara vez están disponibles. Existen diversos trabajos, que muestran el resultado final de un análisis conglomerados no jerárquico depende de lo cercano a la realidad que sea la semilla inicial. No es recomendable que el software la elija de manera aleatoria.")
    )

    text_tbl %>%
      kable(caption = "Cuadro Comparativo: Resumen del Análisis Clúster",
         aling = "c") %>%
   kable_classic_2(html_font = "sans-serif",
                   lightable_options = c("hover", "rayado")) %>%
      row_spec(0,
           bold = T,
           color = "white",
           background = "#505") %>% 
      kable_paper(full_width = F) %>% 
      footnote(general = "Elaboración propia con base en: “Kassambara, A. (2017). Obtenido de Practical Guide To Cluster Analysis in R. Unsupervised Machine Learning.”", general_title = "Fuente:")
Cuadro Comparativo: Resumen del Análisis Clúster
Analálisis_Cluster Técnicas_Disponibles Ventajas Desventajas
Jerárquico: Prentende encontrar grupos discretos según la similitud de sus elementos. Estos grupos se organizan de forma jerárquica y pueden visualizarse a través de un dendrograma. Por lo tanto, en este tipo de análisis no se requiere determinar el número de clústeres de manera previa, estos métodos se dividen en aglomerativo y divisivo. Método de vinculación Simple;
Método de vinculación Completo;
Método del promedio entre grupos;
Método Ward;
Método centroide.
Es un algoritmo que ofrece ventajas notables, como la generación de una estructura ilustrativa para determinar el número de conglomerados a través del dendrograma. Su implementación es fácil y accesible, siendo comparativamente más confiable y rápido que la agrupación jerárquica. Destaca en situaciones de error y puede ser más eficiente computacionalmente, especialmente con un valor pequeño de K. Por tanto, se considera que K-Means se presenta como una técnica versátil y estable. La irreversibilidad de decisiones incorrectas, ya que no se pueden deshacer pasos anteriores. La complejidad temporal puede resultar en cálculos prolongados, limitando su eficiencia. Además, la necesidad de una gran cantidad de cálculos puede restringir la aplicabilidad en conjuntos de datos extensos, y la imposibilidad de modificar una mala partición una vez realizada presenta un desafío adicional en términos de flexibilidad.
No Jerárquico: Se conoce de primeras el número k de grupos que desea, y las observaciones son entonces asignadas a cada uno de esos k conglomerados, es por ello que se maximiza la homogeneidad de los sujetos asignados a un mismo grupo y la heterogeneidad entre los distintos conglomerados. k-medias; Clara; k-medoides. Maximiza la homogeneidad asignados a un mismo grupo y la heterogeneidad entre los distintos conglomerados. Además permite al investigador elegir la cantidad de grupos deseados después de la ejecución del algoritmo. Este enfoque requerirá de suministrar los centroides iniciales (valores medios de las variables que caracterizan las observaciones en cada uno de esos grupos, se le conocen de igual manera como semillas) y estos rara vez están disponibles. Existen diversos trabajos, que muestran el resultado final de un análisis conglomerados no jerárquico depende de lo cercano a la realidad que sea la semilla inicial. No es recomendable que el software la elija de manera aleatoria.
Fuente:
Elaboración propia con base en: “Kassambara, A. (2017). Obtenido de Practical Guide To Cluster Analysis in R. Unsupervised Machine Learning.”

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.

Jerárquicas.

Aglomerativos y Disociativos.

El agrupamiento aglomerativo funciona de manera “de abajo hacia arriba”. Es decir, cada objeto se considera inicialmente como un grupo de un solo elemento. En cada paso del algoritmo, los dos grupos que son más similares se combinan en un nuevo grupo más grande. Este procedimiento se repite hasta que todos los puntos son miembros de un solo grupo grande (raíz).

Lo contrario del agrupamiento aglomerativo es el agrupamiento divisivo, que también se conoce como DIANA (Divise Analysis) y funciona de manera “de arriba hacia abajo”. Comienza con la raíz, en la que todos los objetos están incluidos en un solo clúster. En cada paso de la iteración,el grupo más heterogéneo se divide en dos. El proceso se repite hasta que todos los objetos están en su propio grupo.

Hay que tener en cuenta que el agrupamiento aglomerativo es bueno para identificar pequeños grupos. El agrupamiento divisivo es bueno para identificar grandes grupos. Nos centraremos principalmente en el agrupamiento jerárquico aglomerativo.

Para realizar un agrupamiento jerárquico aglomerativo utilizaremos el software R:

1°.Preparamos los datos.

2°.Cálculo de información de (des)similitud entre cada par de objetos en los datos.

3°.Uso de la función de vinculación para agrupar objetos en un árbol de clúster jerárquico, en función de la información de distancia generada en el paso 1. Los objetos/agrupaciones que están muy cerca se vinculan mediante la función de vinculación.

4°.Determinar dónde cortar el árbol jerárquico en grupos. Esto crea un partición de los datos.

Estructura y preparación de datos

Los datos deben ser una matriz numérica con: filas que representan observaciones (individuos); y columnas que representan variables.

Tenga en cuenta que, por lo general, se recomienda estandarizar las variables en el conjunto de datos antes de realizar análisis posteriores. La estandarización hace que las variables sean comparables, cuando se miden en diferentes escalas. Por ejemplo, una variable puede medir la altura en metros y otra variable puede medir el peso en kg. La función R scale() se puede usar para la estandarización.

library(factoextra)
# Cargar los datos 
data("USArrests")

# Estandarizar los datos 
df <- scale(USArrests)

# Mostrar la cabeza de las primeras 6 filas
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

Medidas de similitud.

Existen muchos métodos para calcular la información de (des)similitud, incluidas las distancias Euclidiana y Manhattan (Capítulo 3). En el software R, puede usar la función dist() para calcular la distancia entre cada par de objetos en un conjunto de datos. Los resultados de este cálculo se conocen como matriz de distancia o disimilitud.

De forma predeterminada, la función dist() calcula la distancia euclidiana entre objetos; sin embargo, es posible indicar otras métricas utilizando el método de argumento.

Miremos el siguiente ejemplo, donde considere el conjunto de datos base R USArrests, se puede calcular la matriz de distancia de la siguiente forma:

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

Hay que tener en cuenta que la función dist() calcula la distancia entre las filas de una matriz de datos utilizando el método de medida de distancia especificado.

Para ver fácilmente la información de distancia entre objetos, reformateamos los resultados de la función dist() en una matriz usando la función as.matrix() . En esta matriz, el valor en la celda formada por la fila i, la columna j, representa la distancia entre el objeto i y el objeto j en el conjunto de datos original.

Vinculación.

La función de vinculación toma la información de distancia, devuelta por la función dist(), y agrupa pares de objetos en grupos en función de su similitud. A continuación, estos grupos recién formados se vinculan entre sí para crear grupos más grandes. Este proceso se repite hasta que todos los objetos del conjunto de datos original se vinculan en un árbol jerárquico.

Tomando por ejemplo, una matriz de distancia “res.dist” generada por la función dist(), la función base de R hclust() puede usarse para crear el árbol jerárquico.

res.hc <- hclust(d = res.dist, method = "ward.D2")
  • d: una estructura de disimilitud producida por la función dist() .

  • Método: el método de aglomeración (vinculación) que se utilizará para calcular la distancia entre

Los valores permitidos son uno de “ward.D”, “ward.D2”, “single”, “complete”, “average”, “mcquitty”, “median” o “centroid”.

Existen muchos métodos de aglomeración de grupos. Sin embargo, los métodos de vinculación más comunes son los siguientes:

  • Vinculación máxima o completa.

  • Enlace mínimo o único.

  • Enlace medio o promedio.

  • Enlace centroide

  • Método de la varianza mínima de Ward.

En cada paso, se fusionan el par de clústeres con una distancia mínima entre clústeres. Nótese que, en cada etapa del proceso de agrupamiento, los dos agrupamientos que tienen la menor distancia de vinculación están vinculados entre sí.

Por otro lado, el clúster del paquete R facilita la realización de análisis de clústeres en R. Proporciona la función agnes() y diana() para calcular el agrupamiento aglomerativo y divisivo, respectivamente. Estas funciones realizan todos los pasos necesarios por usted. No necesita ejecutar las funciones scale(), dist() y hclust() por separado.

Las funciones se pueden ejecutar de la siguiente manera:

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

Anidamiento aglomerativo. res.agnes <- agnes(x = EE.UU. arrestos, # matriz de datos stand = TRUE, # Estandarizar la métrica de datos =“euclidean”, # métrica para el método de matriz de distancia = “ward”

Método de vinculación.

Analisis Divisivo Clustering. res.diana <- diana(x = USAarrestos, # matriz de datos stand = TRUE, # estandarizar la métrica de datos = “euclidean” # métrica para la matriz de distancia )

Después de ejecutar agnes() y diana(), puede usar la función fviz_dend()[de factoextra] para visualizar el resultado:

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

No Jerárquicas.

k-medias

Está técnica agrupa las observaciones en k cluster diferentes, donde el número k es determinado por el analista antes de ejecutar el algoritmo. Entre otras palabras encuentra los k mejores cluster, comprendiendo a mejor cluster el cual posee varianza interna sea lo más pequeño posible.

SINTAXIS

# Generar datos (puedes reemplazar esto con tus propios datos)
set.seed(123)  # Para reproducir
datos <- matrix(rnorm(100 * 2), ncol = 2)  # 100 filas, 2 columnas

# Aplicar k-means con k=3 (como ejemplo)
k <- 3

# aplica el algorirmo de k-medias a tus datos
resultado_kmeans <- kmeans(datos, centers = k)

# Mostrar los resultados
print(resultado_kmeans)
## K-means clustering with 3 clusters of sizes 38, 29, 33
## 
## Cluster means:
##          [,1]       [,2]
## 1 -0.66333772 -0.6219885
## 2 -0.02025692  1.0093022
## 3  1.05560227 -0.4966328
## 
## Clustering vector:
##   [1] 1 2 3 1 1 3 3 1 1 2 3 2 3 1 2 3 3 1 3 1 1 1 1 1 2 1 3 2 1 3 2 2 3 3 3 2 3
##  [38] 2 2 1 2 1 1 3 3 1 1 2 2 1 2 2 2 3 1 3 1 3 2 3 2 1 1 2 1 2 2 1 3 3 1 1 3 2
##  [75] 1 3 1 1 2 1 1 2 1 3 1 3 2 3 2 3 3 3 2 1 3 2 3 3 1 1
## 
## Within cluster sum of squares by cluster:
## [1] 23.92627 22.26036 24.96196
##  (between_SS / total_SS =  59.4 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"

k-medoides

Es un método muy cercano a k-medias en relación a que ambos agrupan las observaciones en k cluster, donde k es un valor preestablecido por el investigador. La diferencia entre este método es que cada cluster está representado por una observación presente en el cluster, por otra parte k-medias cada cluster está representado por su centroide.

El algoritmo más utilizado para aplicar K-medoides se conoce como PAM (Partitioning Around Medoids) y sigue los siguientes pasos:

  1. Seleccionar k observaciones aleatorias como medoides iniciales.

  2. Calcular la matriz de distancia entre todas las observaciones si esta no se ha Calculado anteriormente.

  3. Asignar cada observaciones a su medoid más cercano.

  4. Cada uno de los cluster creados, comprobar si seleccionando otra observación como medoid se consigue reducir la distancia promedio del cluster, si esto sucedes, seleccionar la observación que consigue una mayor reducción como nuevo medoid

  5. Si al menos un medoid ha cambiado en el paso 4, volver al paso 3, por el contrario, finaliza el proceso.

Realizar está técnica se utiliza de una libreria la cual es cluster, siendo así, una conjunto de herramientas y algoritmos centralizado al análisis de conglomerados (clustering), ya sea jerárquicos como no jerárquicos. Proporciona funciones como realizar agrupamientos de datos, de igual manera, identificar patrones y estructuras dentro del conjunto de datos sin etiquetas anteriormente definidas.

SINTAXIS

# Instalar la libreria "cluster"
# Cargar el paquete cluster
library(cluster)

# Generar datos de ejemplo (puedes reemplazar esto con tus propios datos)
set.seed(123)  
datos <- matrix(rnorm(100 * 2), ncol = 2)  # 100 filas, 2 columnas

# Aplicar k-medoids con k=3 
k <- 3

# aplica el algoritmo k-medoids a los datos, utilizando "k" para especificar el número de clústeres
resultado_kmedoids <- pam(datos, k)

# Mostrar los resultados
print(resultado_kmedoids)
## Medoids:
##      ID                       
## [1,]  1 -0.56047565 -0.7104066
## [2,] 52 -0.02854676  0.7690422
## [3,] 90  1.14880762 -0.4992920
## Clustering vector:
##   [1] 1 2 3 1 1 3 3 1 1 2 3 2 1 2 2 3 2 1 3 1 1 1 1 1 2 1 3 2 1 3 2 2 3 3 3 2 3
##  [38] 2 2 1 2 1 1 3 3 1 1 2 2 1 2 2 2 3 1 3 2 3 2 1 2 1 1 2 1 2 2 1 2 3 1 1 3 2
##  [75] 1 3 2 1 2 1 1 2 1 3 1 3 2 2 2 3 3 3 2 1 3 2 3 3 1 1
## Objective function:
##     build      swap 
## 0.8127219 0.7353591 
## 
## Available components:
##  [1] "medoids"    "id.med"     "clustering" "objective"  "isolation" 
##  [6] "clusinfo"   "silinfo"    "diss"       "call"       "data"

CLARA

Es un método que combina la idea de k-medoids con el resampling con el objetivo de poder aplicarse a grandes volúmenes de datos. Clara selecciona una muestra aleatoria de un tamaño determinado y le aplica el algortimo de PAM (k-medoids) para encontrar los cluster óptimos acordes a esa muestra. Utilizando esos medoids se agrupan las observaciones de todo el set de datos, repitiendo dicho proceso de manera predeterminada con la finalidad de reducir el bias del muestreo. Por último, se seleccionan como clusters finales los obtenidos con aquellos medoids que han conseguido menor suma total de distancias.

Pasos del algoritmo CLARA:

  1. Se divide aleatoriamente el set de datos en n partes de igual tamaño, donde n es un valor que determina el investigador.

  2. Para cada una de las n partes:

-   Aplicar el algoritmo PAM e identificar cuáles son los k medoids.

-   Utilizando los medoids agrupar todas las observaciones del set de
datos.

-   Calcular la suma total de las distancias entre cada observaciones
del set de datos y su correspondiente medoid.
  1. Seleccionar como clustering final aquel que ha conseguido menor suma total de distancias intra-cluster en los pasos anteriores.

SINTAXIS

# Cargar el paquete cluster
library(cluster)

# Generar datos de ejemplo (puedes reemplazar esto con tus propios datos)
set.seed(123)  # Para reproducibilidad
datos <- matrix(rnorm(100 * 2), ncol = 2)  # 100 filas, 2 columnas

# Aplicar CLARA con k=3 
k <- 3

# samples específica el número de muestran que se extraerán aleatoriamente del conjunto de datos para realizar el análisis. Un valor más alto puede llevar a resultados más estables y por último pamlike el cual indica si usar una versión modificada del algoritmo PAM que es similar a k-medoids
resultado_clara <- clara(datos, k, samples = 5, pamLike = TRUE)

# Mostrar los resultados
print(resultado_clara)
## Call:     clara(x = datos, k = k, samples = 5, pamLike = TRUE) 
## Medoids:
##             [,1]       [,2]
## [1,] -0.56047565 -0.7104066
## [2,] -0.02854676  0.7690422
## [3,]  0.87813349 -0.4224968
## Objective function:   0.7371177
## Clustering vector:    int [1:100] 1 2 3 1 1 3 3 1 1 2 3 2 3 2 2 3 3 1 ...
## Cluster sizes:            35 32 33 
## Best sample:
##  [1]   1   2   3   5   8   9  12  15  16  23  25  26  29  32  34  35  37  39  41
## [20]  42  43  44  47  51  52  54  58  59  61  65  67  69  73  76  80  86  87  89
## [39]  91  92  93  96  97  98  99 100
## 
## Available components:
##  [1] "sample"     "medoids"    "i.med"      "clustering" "objective" 
##  [6] "clusinfo"   "diss"       "call"       "silinfo"    "data"

4. Del texto: Kassambara, A. (2017). Practical Guide to Cluster Analysis in R: Unsupervised Machine Learning (Multivariate Analysis) (1st ed.). STHDA, disponible en: https://xsliulab.github.io/Workshop/week10/r-cluster-book.pdf, se desarrollaron los siguientes ejemplos:

Ejemplo Capitulo 4: K-Means Clustering.

Cálculo de k-medias de agrupamiento en R.

Datos

library(dplyr)
data("USArrests")  
df <- scale (USArrests)

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

Paquetes y funciones de R requeridos:

La función R estándar para la agrupación en clústeres de k-medias es k significa() [estadisticas paquete], cuyo formato simplificado es el siguiente: k significa(x, centros, iter.max = 10, nstart = 1).

• X: matriz numérica, marco de datos numéricos o un vector numérico • centros: Los valores posibles son el número de conglomerados (k) o un conjunto de centros de conglomerados iniciales (distintos). Si es un número, se elige un conjunto aleatorio de filas (distintas) en x como centros iniciales. • iter.max: El número máximo de iteraciones permitidas. El valor predeterminado es 10. • nstart: El número de particiones iniciales aleatorias cuando los centros son un número. A menudo se recomienda probar nstart> 1.

Para crear un hermoso gráfico de los clústeres generados con el k significa() función, utilizará la factoextra paquete.

Estimación del número óptimo de conglomerados.

La agrupación de k-means requiere que los usuarios especifiquen el número de agrupaciones que se generarán.

La idea es calcular la agrupación de k-medias utilizando diferentes valores de las agrupaciones k. A continuación, se dibuja el wss (dentro de la suma del cuadrado) de acuerdo con el número de grupos. La ubicación de una curva (rodilla) en la parcela se considera generalmente como un indicador del número apropiado de grupos.

La función R fviz_nbclust() [en factoextra paquete] proporciona una solución conveniente para estimar el número óptimo de clústeres.

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

El gráfico anterior representa la varianza dentro de los grupos. Disminuye a medida que k aumenta, pero se puede ver una curva (o “codo”) en k = 4. Esta curva indica que los grupos adicionales más allá del cuarto tienen poco valor. En la siguiente sección, clasificaremos las observaciones en 4 racimos.

Calculo de k-means clustering

Como el algoritmo de agrupamiento de k-medias comienza con k centroides seleccionados al azar, siempre se recomienda usar el set.seed () función con el fin de establecer una semilla para R es aleatorio generador de números. El objetivo es hacer reproducibles los resultados, de modo que el lector de este artículo obtenga exactamente los mismos resultados que se muestran a continuación.

El siguiente código R funciona agrupación de k-medias con k = 4

set.seed(123)
km.res <- kmeans(df, 4, nstart = 25)
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"

La salida impresa muestra: • las medias o centros del conglomerado: una matriz, cuyas filas son el número de conglomerados (1 a 4) y las columnas son variables.

• el vector de agrupamiento: un vector de números enteros (de 1: k) que indica el grupo al que se asigna cada punto.

Es posible calcular la media de cada variable por conglomerados utilizando los datos originales:

aggregate(USArrests, by=list(cluster=km.res$cluster), mean)
##   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

Si desea agregar las clasificaciones de puntos a los datos originales, use esto:

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

Accediendo a los resultadoa de la funcion kmeans().

kmeans () La función devuelve una lista de componentes, que incluye:

• grupo: Un vector de números enteros (de 1: k) que indica el grupo al que se asigna cada punto • centros: Una matriz de centros de conglomerados (medias de conglomerados) • totss: La suma total de cuadrados (TSS), es decir (XI ≠ x̄)2. TSS mide la varianza total en los datos. • dentro: Vector de suma de cuadrados dentro del conglomerado, un componente por conglomerado • centro.withinss: Suma total de cuadrados dentro del conglomerado, es decir suma(dentro) • entre: La suma de cuadrados entre grupos, es decir totss ≠ tot.withinss • Talla: El número de observaciones en cada grupo

Se puede acceder a los componentes de la siguiente manera:

# Número de conglomerado 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 de cluster
km.res$size
## [1]  8 13 16 13
# Clúster significa
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

##Visualizacion de k-means clusters.

fviz_cluster(km.res, data = df,

palette = c("#00BFFF", "#FF1493", "#68228B", "#00008B"),
ellipse.type = "euclid", 
star.plot = TRUE, 
repel = TRUE, 
ggtheme = theme_minimal()
)

Ejemplo Capitulo 5: K-Medoids.

Concepto PAM

El uso de medias implica que la agrupación de k medias es muy sensible a los valores atípicos. Esto puede afectar gravemente la asignación de observaciones a los conglomerados. Un algoritmo más robusto es proporcionado por elPAM algoritmo.

Algoritmo PAM

El algoritmo PAM se basa en la búsqueda de k objetos representativos o medoides entre las observaciones del conjunto de datos. Después de encontrar un conjunto de k medoides, los grupos se construyen asignando cada observación al medoide más cercano.

A continuación, se intercambian cada medoide my cada punto de datos no medoide seleccionado y se calcula la función objetivo. La función objetivo corresponde a la suma de las diferencias de todos los objetos con su medoide más cercano.

El paso SWAP intenta mejorar la calidad de la agrupación mediante el intercambio de objetos seleccionados (medoides) y objetos no seleccionados. Si la función objetivo se puede reducir intercambiando un objeto seleccionado con un objeto no seleccionado, entonces se lleva a cabo el intercambio. Esto se continúa hasta que la función objetivo ya no se puede reducir. El objetivo es encontrar k objetos representativos que minimicen la suma de las diferencias de las observaciones con su objeto representativo más cercano.

Calculo de PAM en R

Datos Usaremos los conjuntos de datos de demostración “USArrests,” que comenzamos escalando (Capítulo 2) usando la función R escala() de la siguiente manera:

data("USArrests") # Cargar el conjunto de datos
df <- scale(USArrests) # Escala los datos
head(df, n = 3) # Ver las primeras 3 filas de 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

Estimacion del numero optimo de conglomerados

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

Calculo PAM clustering

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"
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

Accediendo a los resultados de la funcion pam()

La función pam () devuelve un objeto de clase pam cuyos componentes incluyen:

• medoides: objetos que representan grupos

• agrupación: un vector que contiene el número de agrupación de cada objeto

Se puede acceder a estos componentes de la siguiente manera:

# Medoides de racimo: Nuevo México, 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 clúster
head(pam.res$clustering)
##    Alabama     Alaska    Arizona   Arkansas California   Colorado 
##          1          1          1          2          1          1

Visualizacion PAM clusters

Para visualizar los resultados de la partición, usaremos la función fviz_cluster () [paquete factoextra]. Dibuja un diagrama de dispersión de puntos de datos coloreados por números de grupo. Si los datos contiene más de 2 variables, el algoritmo de análisis de componentes principales (PCA), se utiliza para reducir la dimensionalidad de los datos. En este caso, los dos primeros principales las dimensiones se utilizan para graficar los datos.

fviz_cluster(pam.res,

palette = c("#00FF00", "#EE30A7"), 
ellipse.type = "t", 
repel = TRUE, 
ggtheme = theme_classic()
)

Ejemplo Capítulo 6: CLARA - Clustering Large Applications ()

set.seed(1234)
# Genera 500 objetos, divididos en 2 grupos.
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))

# Vista previa de los datos
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
# Cargar la libreria "cluster" y "factoextra"
library(cluster)
library(factoextra)
fviz_nbclust(df,clara,method = "silhouette")+
  theme_classic()

# Calcular CLARA
clara.res <- clara(df,2,samples = 50,pamLike = TRUE)

# Imprimir componentes de clara.res
print(clara.res)
## 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"
# Agregar clasificaciones de puntos a los datos originales
dd <- cbind(df,cluster=clara.res$cluster)
head(dd,n=4)
##             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
# Acceder a los resultados devueltos por clara()
# Medoids
clara.res$medoids
##              x         y
## S121 -1.531137  1.145057
## S455 48.357304 50.233499
# Clustering
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
fviz_cluster(clara.res, palette = c("blue", "red"), # color palette
             ellipse.type = "t", # Concentration ellipse 
             geom = "point", pointsize = 1,
             ggtheme = theme_classic()
)

Ejemplo Capítulo 7: Agglomerative Clustering (Agrupacion Aglomerativa)

# Cargar los datos
data("USArrests")

# Estandarizar los datos
df <- scale(USArrests)

# Mostrar las primeras 6 filas
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
# Calcular la matriz de disimilitud
# df = los datos estandarizados
res.dist <- dist(df,method = "euclidean")

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
res.hc <- hclust(d=res.dist,method = "ward.D2")

# cex: tamaño de etiqueta
fviz_dend(res.hc,cex = 0.5)

# Calcular la distancia cofentica
res.coph <- cophenetic(res.hc)

# Correlación entre distancia cofenética y la distancia original
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 árbol en 4 grupos.
grp <- cutree(res.hc,k = 4)
head(grp,n=4)
##  Alabama   Alaska  Arizona Arkansas 
##        1        2        2        3
# Número de miembros en cada grupo
table(grp)
## grp
##  1  2  3  4 
##  7 12 19 12
# # Obtener los nombres de los miembros del grupo 1 (cluster).
rownames(df)[grp==1]
## [1] "Alabama"        "Georgia"        "Louisiana"      "Mississippi"   
## [5] "North Carolina" "South Carolina" "Tennessee"
# Cortar en 4 grupos y colorear por grupos.
fviz_dend(res.hc, k = 4, # Cut in four groups
          cex = 0.5, # label size
          k_colors = c("blue", "green", "#E7B800", "red"),
          color_labels_by_k = TRUE, # color labels by groups
          rect = TRUE # Add rectangle around groups
)

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

Ejemplo Capítulo 8: Comparacion de Dendogramas.

1°. Preparamos la data:

Para hacer legibles los gráficos, generados en las siguientes secciones, trabajaremos con un pequeño subconjunto aleatorio del conjunto de datos. Por lo tanto, usaremos la función sample () para seleccionar al azar 10 observaciones entre las 50 observaciones contenidas en el conjunto de datos:

df <- scale(USArrests)

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

2°. Comparamos dendrogramas.

Comenzamos creando una lista de dos dendrogramas calculando agrupamiento jerárquico (HC) usando dos métodos de enlace diferentes (“promedio” y “ward.D2”). A continuación, transformamos los resultados como dendrogramas y creamos una lista para contener los dos dendrogramas.

library(dendextend)
## Warning: package 'dendextend' was built under R version 4.3.2
## 
## ---------------------
## Welcome to dendextend version 1.17.1
## Type citation('dendextend') for how to cite the package.
## 
## Type browseVignettes(package = 'dendextend') for the package vignette.
## The github page is: https://github.com/talgalili/dendextend/
## 
## Suggestions and bug-reports can be submitted at: https://github.com/talgalili/dendextend/issues
## You may ask questions at stackoverflow, use the r and dendextend tags: 
##   https://stackoverflow.com/questions/tagged/dendextend
## 
##  To suppress this message use:  suppressPackageStartupMessages(library(dendextend))
## ---------------------
## 
## Attaching package: 'dendextend'
## The following object is masked from 'package:stats':
## 
##     cutree
# Calculamos la matriz de disimilitud o de distancia
res.dist <- dist(df, method = "euclidean")
# Ejecuamos los agrupamientos jerarquicos
hc1 <- hclust(res.dist, method = "average")
hc2 <- hclust(res.dist, method = "ward.D2")
# Creamos los dos dendogramas
dend1 <- as.dendrogram (hc1)
dend2 <- as.dendrogram (hc2)
# Creamos una lista que contenga los dos dendogramas
dend_list <- dendlist(dend1, dend2)

# Comparando Visualmente los dos dendogramas
tanglegram(dend1, dend2)

# Perzonalizado se veria asi:
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))
)

3°. Matriz de Correlacion entre una lista de dendogramas.

### Estas matriz se pueden usar cuando sean mas de dos dendogramas, 
### primero deben de estar en una lsita

# Matriz de Correlacion Cofenetica
cor.dendlist(dend_list, method = "cophenetic") 
##           [,1]      [,2]
## [1,] 1.0000000 0.9925544
## [2,] 0.9925544 1.0000000
# Matriz de Correlacion de Baker
cor.dendlist(dend_list, method = "baker") 
##           [,1]      [,2]
## [1,] 1.0000000 0.9895528
## [2,] 0.9895528 1.0000000
### Para tener la correlacion entre solo dos dendogramas, se puede asi:

# Cophenetic correlation coefficient
cor_cophenetic(dend1, dend2)
## [1] 0.9925544
# Baker correlation coefficient
cor_bakers_gamma(dend1, dend2)
## [1] 0.9895528
### Para comparar multiples dendogramas, se puede asi:


# Creamos multiples Dendogramas encadenando. Cada dendograma utiliza un metodo distinto
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

# Elaboramos la Matriz de Correlaciones
dend_list <- dendlist(
  "Complete" = dend1,
  "Single" = dend2,
  "Average" = dend3,
  "Centroid" = dend4
)
cors <- cor.dendlist(dend_list)
# Print correlattion matrix
round(cors, 2) %>%
  kable(caption = "Matriz de Correlacion de Multiples Dendogramas",
        align = "c",
        digits = 6) %>%
  kable_classic_2(html_font = "sans-serif",
                  lightable_options = c("hover", "striped")) %>%
  row_spec(0,
           bold = T,
           color = "white",
           background = "#505")
Matriz de Correlacion de Multiples Dendogramas
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 0.92 loaded
corrplot(cors, "pie", "lower")

Capitulo 9: Visualizacion de Dendogramas.

1°. Preparamos la Data:

# Load data
data(USArrests)
# Calculamo las distancias y los agrupamiento jerárquico
dd <- dist(scale(USArrests), method = "euclidean")
hc <- hclust(dd, method = "ward.D2")

2°. Vizualizando los dendogramas:

library(dendextend)
library(factoextra)
library(ggplot2)
library(khroma)

fviz_dend(hc, cex = 0.5)

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

### Para poner en una posicion horizontal el dendograma
fviz_dend(hc, cex = 0.5, horiz = TRUE)

### Realizamos la Particion o corte del Arbol en multiples grupos. 
### Son los mismos del capitulo 7

fviz_dend(hc , k = 4, # Cut in four groups
          cex = 0.5, # label size
          k_colors = "default",
          color_labels_by_k = TRUE, # color labels by groups
          rect = TRUE, # Add rectangle around groups
          rect_border = "default",
          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_light() # Change theme
)

Los valores permitidos para k_color incluyen paletas de cerveza del paquete RColorBrewer (p. Ej., “RdBu”, “Blues”, “Dark2”, “Set2”,…;) Y paletas de revistas científicas del paquete ggsci R (p. Ej., “Npg”, “aaas”,” Lanceta “,” jco “,” ucscgb “,” uchicago “,” simpsons “y” rickandmorty “).

En el código generado en R, cambiaremos los colores del grupo usando “jco” (revista de oncología clínica) paleta de color:

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

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

### Para crear un dendograma circular
fviz_dend(
  hc,
  cex = 0.5,
  k = 4,
  k_colors = "jco",
  type = "circular"
)

### Para trazar un árbol de tipo filogénico, 
### use type = "phylogenic" y repel = TRUE (para evitar la superposición de etiquetas).
library(igraph)
fviz_dend(
  hc,
  k = 4,
  k_colors = "jco",
  type = "phylogenic",
  repel = TRUE
)

El diseño predeterminado para árboles filogenéticos es “layout.auto”. Los valores permitidos son uno de: c (“layout.auto”, “layout_with_drl”, “layout_as_tree”, “layout.gem”, “layout.mds”, “layout_with_lgl”). Para leer más sobre estos diseños, lea la documentación del paquete igraph R.

Probemos phylo.layout = “layout.gem”:

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

3°. Dendograma para grandes conjuntos de datos:

### Para Hacer Zoom
fviz_dend(hc, xlim = c(1, 20), ylim = c(1, 8))

### Trazado de un subarbol

#### Cortar el dendrograma y visualizar la versión truncada:

# 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)

##### Trazar subárboles dendrogramas:

# Plot the whole dendrogram
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")

# Plot subtree 2, en forma circular 

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

#### Guardando en pdf un dendograma sin perder resolucion 

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

4°. Manipulando un dendograma utilizando la libreria dendextend:

# COdigo Estandar para crear un dendograma
data <- scale(USArrests)
dist.res <- dist(data)
hc <- hclust(dist.res, method = "ward.D2")
dend <- as.dendrogram(hc)
plot(dend)

# Usando la libreria dendextend
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)

5°. Personalizando los dendogramas con la libreria dendextend:

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)

5. 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”.

Cluster Analysis on Suicide Victims.

Panorama general de las tasas de suicidio de 1985 a 2016.

Elaborado por: {@KRYSTAL DIXON}, https://www.kaggle.com/code/ksvrd1/cluster-analysis-on-suicide-victims.

Análisis de conglomerados sobre víctimas de suicidio.

La muerte por suicidio se encuentra entre las principales causas de muerte a nivel mundial, particularmente entre personas entre 15 y 49 años. Para abordar este tema es necesario comprender a las víctimas, qué hace que sean similares o diferentes, su demografía, etc. Usaré R para realizar un análisis de conglomerados utilizando agrupamiento jerárquico. La agrupación nos permite segmentar la población de víctimas de suicidio en función de similitudes dentro de parámetros determinados. Luego perfilaré los grupos según las características demográficas para evaluar más a fondo quiénes son las víctimas por grupo. Realizaré dos análisis principales: bivariado y resúmenes de medias de cada grupo. Se visualizarán utilizando gráficos 2D y un gráfico de serpiente, respectivamente. He elegido seis atributos de segmentación, todas las variables seleccionadas se utilizarán para crear perfiles y se describen a continuación.

Atributos de segmentación:

  • GDP per capita
  • Suicide Incidence
  • HDI for Year
  • Suicides Rate(per 100k population)
  • GDP Year

Atributos de perfilado:

  • Country
  • Sex
  • Age
  • Generation
  • Year
  • All Segmenting Attributes
library(tidyverse) #load package
sr <- read_csv("C:/Users/guada/Desktop/Jazz/CICLO II 2023/MAE118 2023/Trabajo_Grupal02/master.csv/master.csv") #load dataset
print(sr)
## # A tibble: 27,820 × 12
##    country  year sex    age         suicides_no population `suicides/100k pop`
##    <chr>   <dbl> <chr>  <chr>             <dbl>      <dbl>               <dbl>
##  1 Albania  1987 male   15-24 years          21     312900                6.71
##  2 Albania  1987 male   35-54 years          16     308000                5.19
##  3 Albania  1987 female 15-24 years          14     289700                4.83
##  4 Albania  1987 male   75+ years             1      21800                4.59
##  5 Albania  1987 male   25-34 years           9     274300                3.28
##  6 Albania  1987 female 75+ years             1      35600                2.81
##  7 Albania  1987 female 35-54 years           6     278800                2.15
##  8 Albania  1987 female 25-34 years           4     257200                1.56
##  9 Albania  1987 male   55-74 years           1     137500                0.73
## 10 Albania  1987 female 5-14 years            0     311000                0   
## # ℹ 27,810 more rows
## # ℹ 5 more variables: `country-year` <chr>, `HDI for year` <dbl>,
## #   `gdp_for_year ($)` <dbl>, `gdp_per_capita ($)` <dbl>, generation <chr>

Un vistazo al conjunto de datos sobre las tasas de suicidio de 1985 a 2016.

El siguiente tbl muestra todas las variables en este conjunto de datos. Cada punto de datos representa cifras y tasas de suicidio para cada país por año, género y grupo de edad.

glimpse(sr) #glimpse data
## Rows: 27,820
## Columns: 12
## $ country              <chr> "Albania", "Albania", "Albania", "Albania", "Alba…
## $ year                 <dbl> 1987, 1987, 1987, 1987, 1987, 1987, 1987, 1987, 1…
## $ sex                  <chr> "male", "male", "female", "male", "male", "female…
## $ age                  <chr> "15-24 years", "35-54 years", "15-24 years", "75+…
## $ suicides_no          <dbl> 21, 16, 14, 1, 9, 1, 6, 4, 1, 0, 0, 0, 2, 17, 1, …
## $ population           <dbl> 312900, 308000, 289700, 21800, 274300, 35600, 278…
## $ `suicides/100k pop`  <dbl> 6.71, 5.19, 4.83, 4.59, 3.28, 2.81, 2.15, 1.56, 0…
## $ `country-year`       <chr> "Albania1987", "Albania1987", "Albania1987", "Alb…
## $ `HDI for year`       <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ `gdp_for_year ($)`   <dbl> 2156624900, 2156624900, 2156624900, 2156624900, 2…
## $ `gdp_per_capita ($)` <dbl> 796, 796, 796, 796, 796, 796, 796, 796, 796, 796,…
## $ generation           <chr> "Generation X", "Silent", "Generation X", "G.I. G…
#removing missing values
sr_no_na <- sr %>%
  na.omit()

#selecting the segmenting attributes
sr1 <- sr %>%
  na.omit() %>%
  select(suicides_no, `suicides/100k pop`, `gdp_for_year ($)`, `gdp_per_capita ($)`, `HDI for year`)

Resumen de cada punto de datos.

sum <- sr_no_na %>% select(-country, -age, -sex, -`country-year`, -generation) %>% summary()
sum
##       year       suicides_no        population       suicides/100k pop
##  Min.   :1985   Min.   :    0.0   Min.   :     875   Min.   :  0.00   
##  1st Qu.:2000   1st Qu.:    3.0   1st Qu.:  121642   1st Qu.:  1.04   
##  Median :2010   Median :   27.0   Median :  472250   Median :  5.72   
##  Mean   :2005   Mean   :  206.1   Mean   : 1852173   Mean   : 11.99   
##  3rd Qu.:2012   3rd Qu.:  127.2   3rd Qu.: 1500290   3rd Qu.: 15.44   
##  Max.   :2014   Max.   :11767.0   Max.   :43509335   Max.   :187.06   
##   HDI for year    gdp_for_year ($)    gdp_per_capita ($)
##  Min.   :0.4830   Min.   :3.963e+08   Min.   :   313    
##  1st Qu.:0.7130   1st Qu.:1.431e+10   1st Qu.:  4862    
##  Median :0.7790   Median :6.176e+10   Median : 12584    
##  Mean   :0.7766   Mean   :5.477e+11   Mean   : 21074    
##  3rd Qu.:0.8550   3rd Qu.:3.115e+11   3rd Qu.: 30271    
##  Max.   :0.9440   Max.   :1.743e+13   Max.   :126352

Análisis de conglomerados jerárquicos.

La agrupación jerárquica agrupa las observaciones en función de sus distancias por pares. Primero, escalaré los valores ya que existen múltiples unidades de medida entre las variables. Luego, las distancias por pares se calcularán utilizando el método euclidiano.

Visualización de distancias por pares.

El siguiente histograma muestra que una distancia euclidiana de dos es la distancia más frecuente entre las distancias por pares.

#scaling sr1 & euclidean distance of sr1 observations
dist_sr1 <- dist(scale(sr1))

#visualizing pair-wise distances
hist(dist_sr1)

#linkage analysis of clusters
hclust_sr1 <- hclust(dist_sr1, method = "complete")

library(dendextend)

sr1_dendrogram <- as.dendrogram(hclust_sr1)

sr1_dendrogram_color <- color_branches(sr1_dendrogram, h = 8)

#extract cluster group
cluster <- cutree(hclust_sr1, k=4)

#add cluster group values to observations
sr2 <- sr_no_na %>% mutate(cluster = cluster)

Dendrograma de conglomerados.

Usando hclust(), completé un análisis de vinculación usando el método “completo” para vincular distancias. Después de una inspección visual del dendrograma, jugué con varios números de grupo y utilicé varias relaciones bivariadas para encontrar qué cantidad de grupo segmenta mejor los datos. Se consideró el método tradicional de seleccionar k trazando las distancias en función del número de grupos; sin embargo, los datos son demasiado grandes y se identificaron más de 900 grupos.

plot(sr1_dendrogram_color)

Análisis de relaciones bivariadas.

Analicé las diversas combinaciones de distancias por pares utilizando gráficos 2D. Esto se hizo para seleccionar qué variables visualizan mejor los segmentos del conglomerado. Seleccioné variables analizando la forma y la fuerza de varias relaciones bivariadas. Se colocó una línea de regresión en la gráfica para comprender mejor las relaciones.

La relación entre las variables Número de suicidios y PIB por año tuvo la asociación más fuerte de todas las demás relaciones bivariadas, como se muestra a continuación.

#characterizing and visualizing bivariate relationship
sr2_lr <- ggplot(sr2, aes(x = `gdp_for_year ($)`, y = suicides_no)) +
              geom_point() +
              geom_smooth(method = "lm", se = FALSE) +
              scale_y_log10() +
              scale_x_log10()
sr2_lr

Visualizando clusters.

Utilizando las variables seleccionadas (Número de suicidios y PIB por año), construí gráficos 2D para visualizar los grupos. Se agregaron líneas de regresión para cada grupo para demostrar cómo se relacionan las variables dentro de cada grupo. Quité las escalas logarítmicas de cada eje para distinguir los grupos.

#visualizing clusters and their regression line
sr2_plot <- ggplot(sr2, aes(y=suicides_no, x=`gdp_for_year ($)`, color = factor(cluster))) +
                geom_point() +
                geom_smooth(method = "lm", se = FALSE)

sr2_plot
## `geom_smooth()` using formula = 'y ~ x'

Perfilado e interpretación de cada cluster.

Para comprender lo que está sucediendo en cada grupo, visualicé cada grupo y los perfilé según el país, el sexo, la edad y la generación. Sus perfiles se visualizan por color.

Cluster 1: — incluyó la mayor parte de los puntos de datos. La mayoría de las víctimas de suicidio se encuentran en este grupo y no existe un elemento de perfil único basado en los datos que tenemos. Por lo tanto, no se proporciona la imagen; sin embargo, el código se proporciona a continuación para cualquiera que quiera echarle un vistazo.

cluster1 <- sr2 %>%
                filter(cluster ==  1) %>% 
                     ggplot(aes(x = suicides_no, y = `gdp_for_year ($)`, color = sex)) +
                         geom_point() +
                         scale_y_log10() +
                         scale_x_log10()

Cluster 2:

  • Las víctimas del Grupo 2 son de Japón, Ucrania y Estados Unidos.

  • Las víctimas de Ucrania tienen el PIB anual y el número de suicidios más bajos de los tres.

  • Todos son masculinos.

  • Sus edades oscilan entre 15 y 74 años, siendo el grupo de edad de 35 a 54 años el que tiene el mayor valor en Número de suicidios.

El grupo 2 se visualiza a continuación; perfilado por país:

cluster2_country <- sr2 %>%
                filter(cluster ==  2) %>%
                    ggplot(aes(y = suicides_no, x = `gdp_for_year ($)`, color = `country`)) +
                        geom_point()+
                        scale_y_log10() +
                        scale_x_log10() +
                        ggtitle("Cluster 2 GDP ~ No. of Suicides by Country")
cluster2_country

Cluster 3.

  • Las víctimas del Grupo 3 son todas de Estados Unidos.

  • Todos son masculinos.

  • Sus edades oscilan entre 35 y 74 años, siendo el grupo de edad de 35 a 54 años el que tiene el mayor número de observaciones.

  • El grupo 3 se visualiza a continuación; perfilado por grupo de edad.

cluster3_age <- sr2 %>% 
                filter(cluster ==  3) %>%
                    ggplot(aes(y = suicides_no, x = `gdp_for_year ($)`, color = `age`)) +
                        geom_point() +
                          scale_y_log10() +
                          ggtitle("Cluster 3 GDP ~ No. of Suicides by Age")
cluster3_age

Cluster 4:

  • Las víctimas del Grupo 4 son todas de Estados Unidos.

  • Están compuestos por hombres y mujeres; sin embargo, la mayoría de las víctimas en este grupo son mujeres.

  • Sus edades oscilan entre 15 y 75 años o más, y el grupo de edad de 24 a 34 años tuvo el mayor número de suicidios entre 2010 y 2014.

  • Los millennials tienen el mayor número de suicidios entre el año 2011 y 2014.

  • El número de suicidios para cada grupo de edad no ha cambiado mucho desde el año 2000.

El grupo 4 se visualiza a continuación; perfilado por generación:

cluster4_country <- sr2 %>%
                filter(cluster ==  4) %>%
                    ggplot(aes(y = suicides_no, x = `gdp_for_year ($)`, color = `generation`)) +
                        geom_point()+
                        scale_y_log10() +
                        scale_x_log10() +
                        ggtitle("Cluster 4 GDP ~ No. of Suicides by Generation")
cluster4_country

Promedios resumidos por grupo.

En este segundo análisis, resumiré los promedios de cada variable: número de suicidios, suicidios por cada 100.000 personas, PIB por año y PIB per cápita. Los promedios para cada par de grupo/variable se muestran en una tabla. Luego se visualiza en un diagrama de serpiente.

#summarizing average for population
pop <- sr2 %>% summarize(
  suicides_no = mean(suicides_no),
  `suicides/100k pop` = mean(`suicides/100k pop`), 
  `gdp_for_year ($)` = mean(`gdp_for_year ($)`),
  `gdp_per_capita ($)` = mean(`gdp_per_capita ($)`),
  `HDI for year` = mean(`HDI for year`)) %>%
  mutate(cluster = "pop") 

#reordering columns
pop <- pop[,c(6,1,2,3,4,5)]

#summarizing average for each cluster
summary <- sr2 %>% group_by(cluster) %>% summarize(
          suicides_no = mean(suicides_no),
          `suicides/100k pop` = mean(`suicides/100k pop`), 
          `gdp_for_year ($)` = mean(`gdp_for_year ($)`),
          `gdp_per_capita ($)` = mean(`gdp_per_capita ($)`),
          `HDI for year` = mean(`HDI for year`))

#combining population and clusters' averages into one tbl
# Convertir la columna cluster en pop a integer
pop$cluster <- as.integer(pop$cluster)

# O bien, convertir la columna cluster en el resumen agrupado a character
summary$cluster <- as.character(summary$cluster)

# Luego, puedes usar add_row sin problemas
summary <- add_row(summary, cluster = "pop",
                   suicides_no = 206.1243,
                   `suicides/100k pop` = 11.99194,
                   `gdp_for_year ($)` = 547663851141,
                   `gdp_per_capita ($)` = 21074.37,
                   `HDI for year` = 0.7766011,
                   .before = 1)
#rotating summary with each cluster as columns
summary <- as.data.frame(t(summary))
summary$profiling_var <- rownames(summary)
summary <- summary[-c(1), ]

#re-adding column names
colnames(summary) <- c("Population", "Cluster 1", " Cluster 2", "Cluster 3", "Cluster 4")
colnames(summary)[6] <- "profiling_var"

#converting summary to a tbl and changing class of col 1-4 as numeric
summary <- tbl_df(summary)
summary <- summary %>% mutate_at(vars(1:5), as.character)
summary <- summary %>% mutate_at(vars(1:5), as.numeric)
summary
## # A tibble: 5 × 6
##   Population `Cluster 1` ` Cluster 2` `Cluster 3` `Cluster 4` profiling_var     
##        <dbl>       <dbl>        <dbl>       <dbl>       <dbl> <chr>             
## 1   2.06e+ 2    1.52e+ 2     5.69e+ 3    9.73e+ 3    2.02e+ 3 suicides_no       
## 2   1.20e+ 1    1.19e+ 1     4.07e+ 1    2.65e+ 1    1.07e+ 1 suicides/100k pop 
## 3   5.48e+11    3.87e+11     4.44e+12    1.48e+13    1.49e+13 gdp_for_year ($)  
## 4   2.11e+ 4    2.07e+ 4     2.97e+ 4    5.15e+ 4    5.19e+ 4 gdp_per_capita ($)
## 5   7.77e- 1    7.75e- 1     8.32e- 1    9.06e- 1    9.06e- 1 HDI for year

Análisis de diagramas de serpientes por conglomerado.

  • Los cluster 3 y 4 empatan con el PIB promedio anual más alto.

  • El cluster 4 tiene el promedio más alto de suicidios.

  • El cluster 2, sin embargo, tiene la tasa de suicidio promedio más alta (por cada 100.000 personas), mientras que tiene el segundo PIB promedio por año y número de suicidios más altos.

  • Los grupos 2 y 3 tienen el número promedio más alto de suicidios y la tasa de suicidio.

#tranforming summary to a long tbl
library(reshape2)
summary_melt <- melt(summary, id = "profiling_var")

#naming columns and converting back to tbl
colnames(summary_melt)[3] <- "mean"
colnames(summary_melt)[2] <- "cluster"
summary_melt <- tbl_df(summary_melt)
snake_plot <- summary_melt %>%
                    ggplot(aes(x=profiling_var, y= mean, group = cluster, color = cluster)) + 
                    geom_line() +
                    geom_point() +
                    scale_y_log10() +
                    ggtitle("Cluster Averages by Variable") +
                    theme(legend.position = c(0.8, 0.8))

snake_plot

Para una mejor visualización, se ha proporcionado una segunda versión del gráfico de serpiente a continuación, sin PIB por año ni IDH por año.

summary_melt2 <- summary_melt %>% filter(profiling_var != "gdp_for_year ($)", profiling_var != "HDI for year")
snake_plot2 <- summary_melt2 %>%
                    ggplot(aes(x=profiling_var, y= mean, group = cluster, color = cluster)) + 
                    geom_line() +
                    geom_point() +
                    scale_y_log10() +
                    ggtitle("Cluster Averages by Variable") +
                    theme(legend.position = c(0.8, 0.8))

snake_plot2

Bibliografía.

Cluster Analysis on Suicide Victims | Kaggle. (n.d.). Retrieved from https://www.kaggle.com/code/ksvrd1/cluster-analysis-on-suicide-victims

Suicide Rates Overview 1985 to 2016. (n.d.). Retrieved from https://www.kaggle.com/datasets/russellyates88/suicide-rates-overview-1985-to-2016?resource=download

ANÁLISIS DE CONGLOMERADOS. (n.d.). Retrieved from https://www.fuenterrebollo.com/Economicas/ECONOMETRIA/SEGMENTACION/CONGLOMERADOS/conglomerados.pdf

Microsoft Word - IN540_041_Cluster.doc. (n.d.). Retrieved from https://www.u-cursos.cl/ingenieria/2010/1/IN540/1/material_docente/bajar?id_material=284403

dendextend: an R package for visualizing, adjusting and comparing trees of hierarchical clustering | Bioinformatics | Oxford Academic. (n.d.). Retrieved from https://academic.oup.com/bioinformatics/article/31/22/3718/240978?login=false

RPubs - Clustering y heatmaps: aprendizaje no supervisado con R. (n.d.). Retrieved from https://rpubs.com/Joaquin_AR/310338

Análisis multivariante aplicado con R. 2a ed. - ALDAS MANZANO, JOAQUIN, URIEL JIMENEZ, EZEQUIEL - Google Libros. (n.d.). Retrieved from https://books.google.com.sv/books?id=FyE3DwAAQBAJ&printsec=copyright&redir_esc=y#v=onepage&q&f=false