La metodología de agrupación mediante K-medias, formulada por MacQueen en 1967, sobresale como el principal algoritmo de aprendizaje no supervisado empleado para dividir un conjunto específico de datos en k grupos (o clústeres), donde k es establecido de antemano por el analista. Su función primordial consiste en la categorización de elementos en diversos grupos, con el objetivo de maximizar la semejanza intraclase (alta concordancia entre elementos dentro del mismo grupo) y minimizar la semejanza interclase (baja concordancia entre elementos de grupos diferentes). Durante este procedimiento, cada grupo se caracteriza a través de su centroide, que representa la media de los puntos asignados a ese grupo.
La esencia subyacente en la agrupación de k-medias radica en la formación de grupos de manera que se minimice la variabilidad total dentro de cada grupo, conocida como variabilidad total intra-grupo. Existen diversos algoritmos de k-medias disponibles, siendo el algoritmo convencional el de Hartigan-Wong (1979). Este algoritmo define la variabilidad total intra-grupo como la suma de las distancias al cuadrado de las distancias euclidianas entre los elementos y el respectivo centroide.
El algoritmo K-medias se puede resumir de la siguiente manera:
Especifique el número de clusters (K) que se crearán (por el analista)
Seleccione aleatoriamente k objetos del conjunto de datos como centros o medios del grupo inicial.
Asigna cada observación a su centroide más cercano, según la distancia euclidiana entre el objeto y el centroide.
Para cada uno de los k grupos, actualice el centroide del grupo calculando los nuevos valores medios de todos los puntos de datos del grupo. El centoide de un grupo K-ésimo es un vector de longitud p que contiene las medias de todas las variables para las observaciones en el grupo K-ésimo; p es el número de variables.
Minimizar iterativamente el total dentro de la suma del cuadrado. Es decir, repita los pasos 3 y 4 hasta que las asignaciones del clúster dejen de cambiar o se alcance el número máximo de iteraciones. De forma predeterminada, el software R utiliza 10 como valor predeterminado para el número máximo de iteraciones.
Para llevar a cabo la agrupación de k-medias en R, se empleará el conjunto de datos de muestra “USArrests”. Es esencial preparar los datos según las indicaciones del capítulo 2, asegurándose de que solo incluyan variables continuas, ya que el algoritmo k-medias se basa en promedios variables.
Con el objetivo de evitar que el algoritmo dependa de una escala arbitraria, se procede a escalar los datos mediante la función scale() en R. El proceso se lleva a cabo de la siguiente manera:
## 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
La función estándar de R para la agrupación de k-medias es kmeans() [paquete de estadísticas], cuyo formato simplificado es el siguiente:
• x: matriz numérica, marco de datos numérico o un vector numérico.
• centers: 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 como centros iniciales un conjunto aleatorio de filas (distintas) en x.
• 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 clusters generados con la función kmeans(), usaremos el paquete factoextra.
## Warning: package 'factoextra' was built under R version 4.3.2
## Loading required package: ggplot2
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
La agrupación en clústeres k-means requiere que los usuarios especifiquen la cantidad de clústeres que se generarán. Una pregunta fundamental es: ¿Cómo elegir el número correcto de conglomerados esperados (k)?
En el capítulo sobre estadísticas de evaluación y validación de conglomerados, se abordarán diversos métodos. Se propone una solución simple que implica calcular la agrupación de k-medias con distintos valores de grupos k. Luego, se representa la suma de los cuadrados dentro del grupo (wss) en función del número de conglomerados. La posición de una curva (punto de inflexión) en el gráfico generalmente se considera un indicador del número adecuado de conglomerados.
Una alternativa práctica para estimar el número óptimo de clústeres es la función R fviz_nbclust() del paquete factoextra.
El gráfico de arriba representa la varianza dentro de los grupos. Disminuye a medida que kaumenta, pero se puede ver una curvatura (o “codo”) en k = 4. Esta curvatura indica que los grupos adicionales más allá del cuarto tienen poco valor. En la siguiente sección, clasificaremos las observaciones en 4 racimos.
Como el algoritmo de agrupamiento de k-medias comienza con k centroides seleccionados aleatoriamente, siempre se recomienda usar la función set.seed() para establecer una semilla para el algoritmo aleatorio de R.
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 los que se muestran a continuación.
El siguiente código R realiza agrupación de k-medias con k = 4:
Dado que el resultado final de la agrupación de k-medias puede ser influenciado por las asignaciones iniciales aleatorias, hemos especificado nstart como 25. Esto indica que R realizará 25 asignaciones iniciales aleatorias diferentes y seleccionará los resultados más óptimos, los cuales tienen la variación más baja dentro del grupo. El valor predeterminado de nstart en R es uno, pero se recomienda encarecidamente aumentar este valor, por ejemplo, a 25 o 50, al realizar la agrupación de k-medias para obtener resultados más estables y confiables.
## 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:
• El grupo means o centers: una matriz, cuyas filas son el número del grupo (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:
## 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, utilice este:
## 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
La función kmeans() devuelve una lista de componentes, que incluye:
• cluster: Un vector de números enteros (de 1:k) que indica el cluster al que se asigna cada punto
• Centers: una matriz de centros de conglomerados (medios de conglomerados)
• totss: La suma total de cuadrados (TSS), es decir (x,-)². TSS mide la varianza total de los datos. • insidess: Vector de suma de cuadrados dentro del grupo, un componente por grupo
• tot.withinss: suma total de cuadrados dentro del grupo, es decir, sum(withinss)
•Betweenss: suma de cuadrados entre grupos, es decir, totss-tot.withinss
•size: el número de observaciones en cada grupo
Se puede acceder a estos componentes de la siguiente manera:
## 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
## Alabama Alaska Arizona Arkansas
## 1 4 4 1
## [1] 8 13 16 13
## 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
Visualizar los resultados de la agrupación de k-medias es esencial para evaluar el número óptimo de conglomerados y comparar análisis de agrupación. La representación gráfica se realiza mediante un diagrama de dispersión, coloreando cada punto según su asignación de grupo.
Cuando los datos tienen más de dos variables, surge la pregunta sobre qué variables elegir para el diagrama de dispersión xy. Una solución eficaz implica reducir la dimensionalidad mediante técnicas como el Análisis de Componentes Principales (PCA), generando dos nuevas variables representativas.
En resumen, al trabajar con conjuntos de datos multidimensionales, se puede realizar PCA y representar los puntos de datos en función de los dos primeros componentes principales. La función fviz_cluster() del paquete factoextra facilita esta visualización, tomando los resultados de k-medias y los datos originales como argumentos. En el gráfico resultante, las observaciones se representan mediante puntos, utilizando componentes principales si el número de variables es mayor que 2. Además, se ofrece la opción de trazar elipses de concentración alrededor de cada grupo, proporcionando una representación visual clara de la estructura de los conglomerados.
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()
)Entre las ventajas de la agrupación, K-medias destaca por su simplicidad y velocidad, siendo un algoritmo eficiente incluso para conjuntos de datos extensos. Su capacidad para manejar grandes volúmenes de datos contribuye a su escalabilidad, convirtiéndolo en una opción viable para aplicaciones prácticas.
Por otra parte, la principal desventaja es la necesidad de que el analista determine previamente el número de clústeres (k), una elección que puede resultar desafiante sin un conocimiento profundo de los datos. La sensibilidad a la inicialización aleatoria de los centros de clúster también plantea problemas, ya que diferentes ejecuciones pueden producir soluciones diversas. Además, la influencia de valores atípicos y la dependencia del orden de los datos son aspectos que deben abordarse.
Para superar la dificultad en la elección de k, se sugiere calcular K-medias para diversos valores de k y seleccionar el óptimo mediante la comparación de resultados de agrupación. La inicialización múltiple del algoritmo con diferentes centros de clúster ayuda a mitigar la variabilidad en los resultados. En cuanto a la sensibilidad a valores atípicos, se propone el uso del algoritmo PAM, menos propenso a distorsiones causadas por datos atípicos. Estas estrategias abordan las limitaciones inherentes de K-medias y mejoran su robustez y aplicabilidad en diversas situaciones.
Una opción robusta como alternativa a la agrupación de k-medias es PAM, que se fundamenta en la noción de medoides. Como se explorará en el próximo capítulo, la realización de la agrupación de clústeres mediante PAM se logra mediante el uso de la función pam() del paquete de clústeres. Adicionalmente, la función pamk() del paquete fpc ofrece una herramienta integral para PAM, incluyendo la impresión del número sugerido de grupos basado en el ancho promedio óptimo de la silueta.
La agrupación de k-medias es una técnica que clasifica observaciones en k grupos según su similitud, siendo cada grupo representado por el valor medio de sus puntos, conocido como centroide. La implementación del algoritmo K-means en R, a través de la función kmeans() del paquete de estadísticas, requiere que los usuarios especifiquen la cantidad deseada de clústeres.
Después de calcular la agrupación, la visualización de los resultados se facilita mediante la función fviz_cluster() del paquete factoextra en R. Este proceso ofrece una manera efectiva de explorar y comprender la estructura de los clústeres generados, permitiendo la interpretación visual de los resultados del análisis de agrupación de k-medias.
LEl algoritmo k-medoids, relacionado con la agrupación k-medias (véase capítulo 4), divide un conjunto de datos en k grupos o clusters. En este enfoque, cada grupo está representado por un punto de datos específico, denominado medoide del cúmulo. El término “medoide” se refiere a un objeto dentro del grupo cuya disimilitud promedio con los demás miembros del grupo es mínima, siendo este el punto más céntrico del cluster. A diferencia de la agrupación k-medias, donde el centro del grupo es el valor medio de todos los puntos, los medoides son objetos representativos de cada grupo.
K-medoides, una sólida alternativa a k-medias, se destaca por su menor sensibilidad al ruido y a los valores atípicos, ya que utiliza medoides en lugar de medias como centros de grupo. Para implementar este algoritmo, es necesario especificar k, el número de clusters a generar, de manera similar al clustering k-medias. Un método efectivo para determinar el número óptimo de conglomerados es el método de silueta, explicado en las secciones siguientes. El algoritmo PAM (Partitioning Around Medoids, Kaufman & Rousseeuw, 1990) es la implementación más común del enfoque de agrupación de k-medoides.
El empleo de medias en la agrupación de k-medias conlleva una alta sensibilidad a los valores atípicos, lo que podría tener un impacto significativo en la asignación de observaciones a los conglomerados. Con el objetivo de abordar esta vulnerabilidad, el algoritmo PAM se presenta como una alternativa más robusta y resistente.
El algoritmo PAM busca k medoides representativos en el conjunto de datos y asigna cada observación al medoide más cercano. A través de un proceso de intercambio, llamado SWAP, se intenta mejorar la calidad de la agrupación intercambiando medoides y objetos no seleccionados. El objetivo es encontrar k objetos representativos que minimicen la suma de las diferencias entre las observaciones y sus medoides más cercanos. En resumen, el algoritmo PAM se desarrolla en dos fases: identificación de medoides y fase de intercambio.
En el algoritmo PAM, se inicia seleccionando k objetos como medoides o, si se proporcionan, se utilizan como tales. Posteriormente, se calcula la matriz de disimilitud si no se ha proporcionado previamente. A continuación, cada objeto se asigna a su medoide más cercano. Para cada grupo, se verifica si algún objeto del grupo reduce el coeficiente de disimilitud promedio; en caso afirmativo, se elige la entidad que maximiza esta disminución como medoide para el grupo. Este proceso se repite hasta que al menos un medoide cambia, momento en el cual se vuelve a asignar cada objeto a su medoide más cercano. El algoritmo concluye cuando no hay cambios en los medoides.
Usaremos los conjuntos de datos de demostración “USArrests”, que comenzamos escalando (Capítulo 2) usando la función R scale() de la siguiente manera:
# Calculando PAM
data("USArrests") # Carga del data set
df <- scale(USArrests)
head(df, n = 3) # Ver primeras 3 filas## 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
Para determinar el número óptimo de grupos, empleamos el método de
silueta promedio en la estimación del algoritmo PAM. Este método implica
calcular el PAM con distintos valores de grupos, seguido por la
representación gráfica de la silueta promedio en función del número de
conglomerados. La silueta media es un indicador de la calidad del
agrupamiento, donde un ancho de silueta promedio elevado denota una
agrupación efectiva. La identificación del número óptimo de
conglomerados, k, se basa en maximizar la silueta promedio dentro de un
rango de valores posibles para k, siguiendo la propuesta de Kaufman y
Rousseeuw (1990). La función R fviz_nbclust() del paquete
factoextra brinda una solución práctica para esta estimación.
Según el siguiente gráfico, el número sugerido de grupos es 2. En la siguiente sección clasificaremos las observaciones en 2 grupos.
El siguiente código R calcula el algoritmo PAM con k=2.
## Medoids:
## ID Murder Assault UrbanPop Rape
## New Mexico 31 0.8292944 1.3708088 0.3081225 1.1603196
## Nebraska 27 -0.8008247 -0.8250772 -0.2445636 -0.5052109
## Clustering vector:
## Alabama Alaska Arizona Arkansas California
## 1 1 1 2 1
## Colorado Connecticut Delaware Florida Georgia
## 1 2 2 1 1
## Hawaii Idaho Illinois Indiana Iowa
## 2 2 1 2 2
## Kansas Kentucky Louisiana Maine Maryland
## 2 2 1 2 1
## Massachusetts Michigan Minnesota Mississippi Missouri
## 2 1 2 1 1
## Montana Nebraska Nevada New Hampshire New Jersey
## 2 2 1 2 2
## New Mexico New York North Carolina North Dakota Ohio
## 1 1 1 2 2
## Oklahoma Oregon Pennsylvania Rhode Island South Carolina
## 2 2 2 2 1
## South Dakota Tennessee Texas Utah Vermont
## 2 1 1 2 2
## Virginia Washington West Virginia Wisconsin Wyoming
## 2 2 2 2 2
## Objective function:
## build swap
## 1.441358 1.368969
##
## Available components:
## [1] "medoids" "id.med" "clustering" "objective" "isolation"
## [6] "clusinfo" "silinfo" "diss" "call" "data"
La salida impresa del algoritmo PAM incluye dos elementos clave: la matriz del grupo de medoides, donde cada fila representa un medoide y las columnas son variables, y el vector de agrupamiento, un conjunto de números enteros (de 1 a k) que señala a qué grupo se asigna cada punto. Si se desea incorporar estas clasificaciones directamente a los datos originales, puede utilizar la siguiente instrucción:
## 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
La función pam() produce un objeto de clase “pam”, cuyos componentes fundamentales son la lista de medoides que representan los grupos y el vector de agrupamiento que asigna cada objeto a su respectivo grupo. Estos resultados brindan una visión detallada de la estructura de los grupos y la asignación de objetos en el conjunto de datos analizado.
## Murder Assault UrbanPop Rape
## New Mexico 0.8292944 1.3708088 0.3081225 1.1603196
## Nebraska -0.8008247 -0.8250772 -0.2445636 -0.5052109
## Alabama Alaska Arizona Arkansas California Colorado
## 1 1 1 2 1 1
Para representar gráficamente los resultados de la partición en clústeres PAM, emplearemos la función fviz_cluster() del paquete factoextra. Esta función genera un diagrama de dispersión que coloreará los puntos de datos según los números de grupo asignados. En situaciones donde los datos abarcan más de dos variables, se implementa el algoritmo de Análisis de Componentes Principales (PCA) para reducir la dimensionalidad de los datos. En este contexto, las dos primeras dimensiones principales se utilizan para visualizar los datos de manera efectiva.
fviz_cluster(pam.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
repel = TRUE, # Avoid label overplotting (slow)
ggtheme = theme_classic()
)El algoritmo K-medoids, conocido como PAM, presenta una sólida alternativa a k-means para la segmentación de conjuntos de datos en grupos de observaciones. En este enfoque, cada grupo se representa mediante un objeto seleccionado internamente denominado medoide, que corresponde al punto más central del grupo. La implementación de PAM requiere que el usuario especifique el número adecuado de clústeres, estimándolo con la función fviz_nbclust del paquete factoextra en R. La función pam() del paquete de clústeres se emplea para calcular PAM, utilizando el formato pam(x, k), donde “x” representa los datos y “k” indica el número de clústeres a generar. Tras realizar la agrupación PAM, la visualización de los resultados se facilita mediante la función fviz_cluster del paquete factoextra, utilizando el formato fviz_cluster(pam.res), donde pam.res representa los resultados de PAM.
CLARA (Clustering Large Applications, Kaufman y Rousseeuw, 1990) constituye una extensión de los métodos k-medoids, como se detalla en el Capítulo 5, diseñada para abordar conjuntos de datos que implican una cantidad considerable de objetos, superando varias miles de observaciones. El objetivo principal es mitigar la carga computacional y los desafíos de almacenamiento de la RAM. Para lograrlo, CLARA implementa un enfoque de muestreo.
En lugar de buscar medoides para todo el conjunto de datos, CLARA adopta un enfoque de muestreo, considerando una pequeña muestra de datos con tamaño fijo. Aplica el algoritmo PAM del Capítulo 5 para obtener un conjunto óptimo de medoides para la muestra, evaluando la calidad de estos medoides mediante la disimilitud promedio con cada objeto en el conjunto de datos completo, definido como la función de costo. CLARA repite los procesos de muestreo y agrupamiento varias veces para reducir el sesgo de muestreo, y los resultados finales corresponden al conjunto de medoides que minimiza el costo.
El algoritmo se inicia dividiendo de manera aleatoria los conjuntos de datos en múltiples subconjuntos, cada uno con un tamaño fijo o tamaño de muestra. Luego, se aplica el algoritmo PAM en cada subconjunto para seleccionar los k objetos representativos, es decir, los medoides. Cada observación en el conjunto de datos completo se asigna al medoide más cercano. Posteriormente, se calcula la media (o suma) de las disimilitudes entre las observaciones y sus respectivos medoides, sirviendo como medida de la calidad de la agrupación. Se conserva el conjunto de subdatos cuya media (o suma) es mínima, y se realiza un análisis más detallado de la partición final.
Para calcular el algoritmo CLARA en R, los datos deben prepararse como se indica en el Capítulo 2. Aquí, generaremos un conjunto de datos aleatorios. Para que el resultado sea reproducible, comenzamos usando la función set.seed().
set.seed(1234)
#Generación de 500 objetos, dividos en dos clusters
df <- rbind(cbind(rnorm(200,0,8), rnorm(200,0,8)),
cbind(rnorm(300,50,8), rnorm(300,50,8)))
#Especificar los nombres de columnas y filas
colnames(df)<- c("x", "y")
rownames(df) <- paste0("S",1:nrow(df))
#Previsualización de 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
La función clara() [paquete de clúster] se puede utilizar para calcular CLARA. El formato simplificado es el siguiente:
Para estimar el número óptimo de clusters en sus datos, es posible utilizar el método de silueta promedio como se describe en el capítulo de clustering de PAM (Capítulo 5). La función R fuiz_nbclust() [paquete factoextra] proporciona una solución para facilitar este paso.
Según el gráfico, el número sugerido de grupos es 2. En la siguiente sección, clasificaremos las observaciones en 2 grupos.
El siguiente código R calcula el algoritmo PAM con k=2.
#Computación CLARA
clara.res <- clara(df, 2, samples=50, pamLike = TRUE)
#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"
La salida de la función clara() presenta componentes clave, incluyendo los medoides que representan los clusters y el vector de clustering que asigna a cada objeto un número de cluster. Adicionalmente, se proporcionan las etiquetas o estuches que numeran las observaciones en la mejor muestra, es decir, la muestra utilizada por el algoritmo CLARA para la partición final. Si se desea incorporar estas clasificaciones directamente a los datos originales, se puede utilizar la instrucción proporcionada.
## 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
## x y
## S121 -1.531137 1.145057
## S455 48.357304 50.233499
## S1 S2 S3 S4 S5 S6 S7 S8 S9 S10
## 1 1 1 1 1 1 1 1 1 1
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.
fviz_cluster(clara.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
geom = "point", pointsize = 1,
ggtheme = theme_classic()
)CLARA (Clustering Large Applications), una extensión del método de clustering PAM (Partitioning Around Medoids) diseñada para grandes conjuntos de datos, busca reducir el tiempo de cálculo en este contexto. Similar a otros algoritmos de partición, requiere que el usuario especifique la cantidad adecuada de clústeres, una estimación posible mediante la función fviz_nbclust del paquete factoextra en R. La función clara() del paquete de clústeres se emplea para calcular CLARA, con el formato clara(x, k, pamLike = TRUE), donde “x” representa los datos y “k” indica el número de clusters a generar. Después de realizar el cálculo con CLARA, los resultados se pueden visualizar utilizando la función fviz_cluster() del paquete factoextra, con el formato fviz_cluster(clara.res), donde clara.res representa los resultados obtenidos con CLARA.
La agrupación jerárquica, también conocida como análisis de conglomerados jerárquicos (HCA), ofrece un enfoque distinto para la clasificación de objetos basado en su similitud, en contraste con la agrupación con particiones. Una característica distintiva es que no requiere la especificación previa del número de clústeres a generar. Este método puede dividirse en dos categorías: el agrupamiento aglomerativo, que parte considerando cada observación como un clúster propio y fusiona sucesivamente los clústeres más similares hasta formar un solo clúster grande, y el agrupamiento divisivo, que comienza con un único grupo que incluye todas las observaciones y se divide sucesivamente en grupos más heterogéneos. El resultado final de la agrupación jerárquica se presenta como un árbol, también conocido como dendrograma.
El dendrograma, una estructura jerárquica multinivel, permite decidir en qué nivel cortar el árbol para formar grupos de objetos de datos. Este capítulo se centra en visualizar la disimilitud entre objetos utilizando dendrogramas. Se describen algoritmos de agrupamiento jerárquico con scripts R para calcular y visualizar resultados, incluyendo técnicas para segmentar dendrogramas en grupos, comparar dos dendrogramas y manejar grandes conjuntos de datos.
La agrupación aglomerativa, también conocida como AGNES (Anidación Aglomerativa), es el enfoque más común para agrupar objetos jerárquicamente según su similitud. Este algoritmo inicia considerando cada objeto como un grupo individual y fusiona progresivamente pares de grupos hasta formar un único grupo que incluye todos los objetos. El resultado es un dendrograma, una representación jerárquica de los objetos.
La agrupación aglomerativa procede “ascendiendo”, considerando inicialmente cada objeto como un grupo individual (hoja). En cada paso, se fusionan los dos grupos más similares para formar un nuevo grupo más grande (nodo), y este proceso continúa hasta que todos los objetos pertenecen a un solo grupo grande (raíz). En contraste, la agrupación divisiva, también conocida como DIANA (Análisis Divisivo), funciona “de arriba hacia abajo”, comenzando con la raíz, donde todos los objetos están en un solo grupo, y divide sucesivamente grupos más heterogéneos en cada iteración.
En la agrupación jerárquica aglomerativa en R, se siguen los siguientes pasos: primero, se preparan los datos; luego, se calculan las medidas de (des)similitud entre cada par de objetos en el conjunto de datos. A continuación, se emplea la función de vinculación para construir un árbol jerárquico de grupos, donde objetos o grupos cercanos se vinculan según la información de distancia. Finalmente, se determina el punto de corte en el árbol jerárquico para formar grupos, logrando así una partición de los datos.
Los datos deben ser una matriz numérica con:
• Filas que representan observaciones (individuos).
• Columnas que representan variables.
#Carga de datos
data("USArrests")
#Estandarizar los datos
df <- scale(USArrests)
#Muestra 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
En el contexto de la agrupación jerárquica, es crucial evaluar la similitud entre objetos o grupos para determinar las fusiones o divisiones adecuadas. Se dispone de diversos métodos para medir la (des)similitud, como las distancias euclidiana y de Manhattan detalladas en el Capítulo 3. En el entorno R, la función dist() permite calcular estas distancias entre cada par de objetos en un conjunto de datos, generando así una matriz de distancia o disimilitud que sirve como base para las decisiones de agrupamiento.
Reformateamos los resultados de la función dist() en una matriz con as.matrix() para visualizar claramente la información de distancia entre objetos en el conjunto de datos original. Cada celda (i, j) representa la distancia entre el objeto i y el objeto j. El código R siguiente muestra las primeras 6 filas y columnas de la matriz de distancia.
## 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
La información de distancia proporcionada por la función dist() se utiliza en la vinculación para agrupar objetos en pares similares, formando grupos que luego se vinculan para crear estructuras jerárquicas más extensas. Este procedimiento se repite hasta que todos los objetos del conjunto de datos original están interconectados en un árbol jerárquico. hclust() puede ser utilizado de la siguiente manera:
Las diferentes técnicas de vinculación en la agrupación jerárquica incluyen la vinculación máxima, mínima, media, centroide y el método de varianza mínima de Ward. La vinculación máxima utiliza la distancia máxima entre elementos de dos conglomerados, produciendo grupos más compactos. La vinculación mínima utiliza la distancia mínima, generando grupos más largos y dispersos. La vinculación media utiliza la distancia promedio, mientras que la vinculación centroide utiliza la distancia entre los centroides de los conglomerados. El método de varianza mínima de Ward minimiza la varianza total dentro de cada conglomerado, fusionando en cada paso el par con la distancia mínima.
Los dendrogramas corresponden a la representación gráfica del árbol jerárquico generado por la función hclust(). El dendrograma se puede producir en R usando la función base plot(res.hc), donde res.hc es la salida de hclust(). Aquí, usaremos la función fuiz_dend()[ en el paquete factoextra R] para producir un hermoso dendrograma. Primero instale factoextra escribiendo esto: install.packages(“factoextra”); A continuación visualice el dendrograma de la siguiente manera:
## Warning: The `<scale>` argument of `guides()` cannot be `FALSE`. Use "none" instead as
## of ggplot2 3.3.4.
## ℹ The deprecated feature was likely used in the factoextra package.
## Please report the issue at <https://github.com/kassambara/factoextra/issues>.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
En el dendrograma que se muestra arriba, cada hoja corresponde a un objeto. A medida que ascendemos en el árbol, los objetos que son similares entre sí se combinan en ramas, que a su vez se fusionan a mayor altura.
Las diferentes técnicas de vinculación en la agrupación jerárquica incluyen la vinculación máxima, mínima, media, centroide y el método de varianza mínima de Ward. La vinculación máxima utiliza la distancia máxima entre elementos de dos conglomerados, produciendo grupos más compactos. La vinculación mínima utiliza la distancia mínima, generando grupos más largos y dispersos. La vinculación media utiliza la distancia promedio, mientras que la vinculación centroide utiliza la distancia entre los centroides de los conglomerados. El método de varianza mínima de Ward minimiza la varianza total dentro de cada conglomerado, fusionando en cada paso el par con la distancia mínima.
## [1] 0.6975266
## [1] 0.7180382
Cortar el dendrograma para formar grupos en la agrupación jerárquica plantea el desafío de determinar el número de grupos y la altura adecuada para el corte. La función cutree() de R, aplicada al árbol generado por hclust(), facilita este proceso al permitir especificar el número deseado de grupos o la altura de corte. Al ejecutar cutree(), se obtiene un vector que asigna a cada observación el número correspondiente al grupo al que pertenece.
## Alabama Alaska Arizona Arkansas
## 1 2 2 3
## grp
## 1 2 3 4
## 7 12 19 12
## [1] "Alabama" "Georgia" "Louisiana" "Mississippi"
## [5] "North Carolina" "South Carolina" "Tennessee"
#Cortar en cuatro grupos y colores por grupo
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,
rect = TRUE
)#Usando la función fviz_cluster()
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())El paquete cluster de R facilita la realización de análisis de clusters en R. Proporciona las funciones agnes() y diana() para calcular clustering aglomerativo y divisivo, respectivamente. Estas funciones realizan todos los pasos necesarios para usted. No es necesario ejecutar las funciones scale(), dist() y hclust() por separado. Las funciones se pueden ejecutar de la siguiente manera:
# Cluster R package
res.agnes <- agnes(x = USArrests, # data matrix
stand = TRUE, # Estandarización de datos
metric = "euclidean",
method = "ward"
)
res.diana <- diana(x = USArrests, # data matrix
stand = TRUE, # Estandarización de datos
metric = "euclidean"
)
fviz_dend(res.agnes, cex = 0.6, k = 4)En el análisis de datos de expresión genética, el agrupamiento jerárquico se emplea como una etapa inicial para investigar los datos. El objetivo es identificar posibles grupos de genes o muestras que presenten patrones similares de expresión genética. En este contexto, se han propuesto diversas medidas de distancia (ver Capítulo 3) para evaluar la similitud o disimilitud entre los ítems, facilitando así la decisión sobre qué ítems deben agruparse.
La agrupación jerárquica es un enfoque de análisis de conglomerados que genera una representación en forma de árbol, conocida como dendrograma, para un conjunto de datos. En este dendrograma, los objetos están conectados entre sí según su nivel de similitud. En R, para llevar a cabo un análisis de conglomerados jerárquico, se inicia calculando la matriz de distancias mediante la función dist(). Posteriormente, esta matriz se utiliza en la función hclust() para obtener el árbol jerárquico. Para una visualización efectiva del dendrograma, se puede emplear la función fviz_dend() del paquete R factoextra. Además, es posible dividir el árbol en grupos definidos por una altura específica utilizando la función cutree().
Tras abordar el cálculo del agrupamiento jerárquico en el Capítulo 7, se presenta ahora la comparación de dos dendrogramas mediante el uso del paquete dendextend en R. Este paquete ofrece diversas funciones para esta tarea, destacando especialmente dos de ellas: tanglegram(), que facilita la comparación visual de dos dendrogramas, y cor.dendlist(), destinada a calcular una matriz de correlación entre dendrogramas.
Usaremos los conjuntos de datos de USArrests base R y comenzaremos estandarizando las variables usando la función scale() de la siguiente manera:
Comenzamos creando una lista de dos dendrogramas calculando la agrupación jerárquica (HC) utilizandodos métodos de vinculación diferentes (“promedio” y “ward.D2”). A continuación, transformamoslos resultados como dendrogramas y creamos una lista para contener los dos dendrogramas.
install.packages(“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
res.dist<-dist(df,method="euclidean")
hc1<- hclust(res.dist, method="average")
hc2<- hclust(res.dist, method="ward.D2")
#Creación de dos dendograms
dend1 <- as.dendrogram (hc1)
dend2 <- as.dendrogram (hc2)
#Creación lista
dend_list <- dendlist(dend1, dend2)En el contexto de la comparación visual de dos dendrogramas, emplearemos la función tanglegram() del paquete dendextend. Esta función traza ambos dendrogramas uno al lado del otro, conectando sus etiquetas con líneas. La calidad de la alineación de los dos árboles puede evaluarse mediante la función entrelazamiento(), donde un coeficiente más bajo indica una mejor alineación, variando entre 1 (entrelazamiento total) y 0 (sin entrelazamiento).
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))
)La función cor.dendlist() se utiliza para calcular la matriz de correlación “Baker” o “Cophenetic” entre una lista de árboles. El valor puede oscilar entre -1 y 1. Un valor cercano a 0 significa que los dos árboles no son estadísticamente similares.
## [,1] [,2]
## [1,] 1.0000000 0.9925544
## [2,] 0.9925544 1.0000000
## [,1] [,2]
## [1,] 1.0000000 0.9895528
## [2,] 0.9895528 1.0000000
## [1] 0.9925544
## [1] 0.9895528
# Creación de múltiples dendrograms
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
# Correlación matrix
dend_list <- dendlist("Complete" = dend1, "Single" = dend2,
"Average" = dend3, "Centroid" = dend4)
cors <- cor.dendlist(dend_list)
round(cors, 2)## Complete Single Average Centroid
## Complete 1.00 0.46 0.45 0.30
## Single 0.46 1.00 0.23 0.17
## Average 0.45 0.23 1.00 0.31
## Centroid 0.30 0.17 0.31 1.00
## Warning: package 'corrplot' was built under R version 4.3.2
## corrplot 0.92 loaded
En capítulos previos, se explicó que un dendrograma es una representación en forma de árbol de datos generados mediante métodos de agrupamiento jerárquico, como se detalló en el Capítulo 7. Este artículo presenta código en R para la visualización y personalización de dendrogramas, además de ofrecer información sobre cómo guardar y ampliar un dendrograma extenso. El proceso comienza con el cálculo de la agrupación jerárquica utilizando conjuntos de datos de USArrests.
#Cargar datos
data(USArrests)
#Computación distancias y clustering
dd <- dist(scale(USArrests), method="euclidean")
hc <- hclust(dd, method= "ward.D2")Para visualizar el dendrograma, usamos los siguientes paquetes y funciones de R:
## Warning: packages 'factoextra', 'dendextend' are in use and will not be
## installed
Usaremos la función fviz_dend()[en el paquete R factoextra] para crear fácilmente un dendrograma usando el gráfico base de R o ggplot2. También proporciona una opción para dibujar dendrogramas circulares y árboles de tipo filogénico. Para crear dendrogramas básicos, escriba esto:
También es posible cortar el árbol a una altura determinada para dividir los datos en múltiples grupos como se describe en el capítulo anterior: Agrupación jerárquica (Capítulo 7). En este caso, es posible colorear las ramas por grupos y agregar un rectángulo alrededor de cada una.
للPara cambiar el tema de la trama, utilice el argumento ggtheme, que permite que los valores incluyan los temas oficiales de gg-plot2 [theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void()] o cualquier otro tema de ggplot2 definido por el usuario.
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
)Los valores permitidos para k_color incluyen paletas de cerveza del paquete RColor Brewer (p. ej. “RdBu”, “Blues”, “Dark2”, “Set2”, …;) y paletas de revistas científicas de gasci R paquete (por ejemplo: “npg”, “aaas”, “lancet”, “jco”, “ucscgb”, “uchicago”, “simpsons” y “rickandmorty”). En el código R a continuación, cambiaremos los colores del grupo usando la paleta de colores “jco”:
#Si quieres dibujar un dendrograma horizontal con rectangulos alrededor de los clusters, usa esto:
fviz_dend(hc, k = 4, cex = 0.4, horiz = TRUE, k_colors = "jco",
rect = TRUE, rect_border = "jco", rect_fill = TRUE)#Si prefieres una figura o dendrograma circular usa la opción type="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 que las etiquetas se sobrecarguen). Esta funcionalidad requiere el paquete R igraph. Asegúrese de que esté instalado antes de escribir el siguiente código R.
library(igraph)## Warning: package 'igraph' was built under R version 4.3.2
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
library(factoextra)
# Suponiendo que 'hc' es el objeto de análisis jerárquico de agrupamiento previamente creado
# Visualización de un dendrograma filogenético
fviz_dend(hc, k = 4, k_colors = "jco", type = "phylogenic", repel = TRUE)El diseño predeterminado para los árboles filogénicos 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.
Cuando realiza el análisis de agrupación jerárquica en un conjunto de datos extenso, puede resultar beneficioso ampliar el dendrograma o representar únicamente un subconjunto de éste. Otra opción viable es generar el dendrograma en una página de gran tamaño en formato PDF, lo cual permite su ampliación sin sufrir pérdida de resolución.
Si desea ampliar los primeros grupos, es posible utilizar la opción xlim e ylim para limitar el área de trazado. Por ejemplo, escriba el siguiente código:
Para trazar un subárbol, seguiremos el procedimiento siguiente:
Cree el dendrograma completo usando fviz_dend() y guarde el resultado en un objeto, llamado dend_plot, por ejemplo.
Utilice la función base de R cut.dendrogram() para cortar el dendrograma, a una altura determinada (h), en múltiples subárboles. Esto devuelve una lista con los componentes Supper y $lower, el primero es una versión truncada del árbol original, también de clase dendrograma, el segundo una lista con las ramas obtenidas al cortar el árbol, cada una un dendrograma.
Visualice subárboles usando fviz_dend().
#Trazar un subárbol de dendrogramas
# Crea un gráfico de todo el dendrograma,
# y extrae los datos del dendrograma
dend_plot <- fviz_dend(hc, k = 4,
cex = 0.5,
k_colors = "jco"
)
dend_data <- attr(dend_plot, "dendrogram") # Extraer datos de dendrograma
# Cortar el dendrograma a la altura h = 10
dend_cuts <- cut(dend_data, h = 10)
# Visualiza la versión truncada que contiene
# dos ramas
fviz_dend(dend_cuts$upper)## Warning in min(-diff(our_dend_heights)): ningún argumento finito para min;
## retornando Inf
#Además puedes graficar arboles circulares de la siguiente manera:
fviz_dend(dend_cuts$lower[[2]], type = "circular")Si tiene un dendrograma grande, puede guardarlo en una página PDF grande, que se puede ampliar sin pérdida de resolución.
pdf("dendrogram.pdf", width=30, height=15)
p<- fviz_dend(hc, k=4, cex=1, k_colors="jco")
print(p)
dev.off## function (which = dev.cur())
## {
## if (which == 1)
## stop("cannot shut down device 1 (the null device)")
## .External(C_devoff, as.integer(which))
## dev.cur()
## }
## <bytecode: 0x00000204a83ebaf8>
## <environment: namespace:grDevices>
El paquete dendextend facilita la modificación visual de dendrogramas y la comparación entre ellos. En esta sección, utilizamos el operador de encadenamiento (%>%) para simplificar el código, convirtiendo múltiples operaciones en una forma más legible y estructurada. Este operador transforma expresiones del tipo x %>% f(y) en f(x, y), permitiendo la lectura secuencial de las operaciones de izquierda a derecha y de arriba a abajo. Los siguientes códigos R ilustran de manera equivalente esta idea.
#Codigo estandar de R para creación de dendrograma
data <- scale(USArrests)
dist.res <- dist(data)
hc <- hclust(dist.res, method = "ward.D2")
dend <- as.dendrogram(hc)
plot(dend)#Codigo de R para creación de dendrograma usando el operador chaining
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)Funciones para personalizar dendrogramas: la función set() [en el paquete dendextend] se puede utilizar para cambiar los parámetros de un dendrograma.
Posibles valores para el argumento que incluyen:
#Ejemplo
library(dendextend)
mycols <- c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07")
dend <- as.dendrogram(hc) %>%
set("branches_lwd", 1) %>%
set("branches_k_color", mycols, k = 4) %>%
set("labels_colors", mycols, k = 4) %>%
set("labels_cex", 0.5)
fviz_dend(dend)En este contexto, se detallan diversas funciones y paquetes para la visualización y personalización de dendrogramas. Entre ellos, destaca fviz_dend() del paquete R factoextra, que ofrece soluciones prácticas para trazar dendrogramas de manera sencilla y estéticamente atractiva. Esta función es versátil, permitiendo la creación de dendrogramas tanto rectangulares como circulares, así como la representación de árboles filogenéticos. Además, se menciona el paquete dendextend, el cual proporciona métodos flexibles para la personalización de dendrogramas, ofreciendo opciones adicionales para adaptar la apariencia según las necesidades específicas del usuario. También se describe cómo realizar la representación gráfica de subconjuntos de dendrogramas extensos, destacando la capacidad de estos paquetes para abordar situaciones con conjuntos de datos de gran tamaño.
El mapa de calor, también conocido como imagen de color falso, ofrece una representación visual de la agrupación jerárquica en datos. Este método transforma los valores de los datos en una escala de colores, permitiendo la observación simultánea de grupos de muestras y características. La agrupación jerárquica se aplica a las filas y columnas de la matriz de datos, reorganizando estas filas y columnas según los resultados de la agrupación. Este proceso posiciona las observaciones similares en proximidad. Los bloques de valores “altos” y “bajos” aparecen contiguos en la matriz de datos. Posteriormente, se utiliza un esquema de colores para la visualización final de la matriz de datos. Esta representación facilita la identificación de variables que pueden ser características distintivas de cada grupo de muestras.
Existe una gran cantidad de paquetes y funciones de R para dibujar mapas de calor estáticos e interactivos, que incluyen:
• heatmap() [función base de R, paquete de estadísticas]: dibuja un mapa de calor simple
• heatmap.2) [paquete gplots R]: dibuja un mapa de calor mejorado en comparación con la función base de R.
• pheatmap() [paquete pheatmap R]: dibuja bonitos mapas de calor y proporciona más control para cambiar la apariencia de los mapas de calor. d3heatmap() [paquete d3heatmap R]: dibuja un mapa de calor interactivo/en el que se puede hacer clic.
• Heatmap() [paquete ComplexHeatmap R/Bioconductor]: dibuja, anota y organiza mapas de calor complejos (muy útil para el análisis de datos genómicos)
Aquí, comenzamos describiendo las 5 funciones R para dibujar mapas de calor. A continuación, nos centraremos en el paquete Complex Heatmap, que proporciona una solución flexible para organizar y anotar múltiples mapas de calor. También permite visualizar la asociación entre diferentes datos de diferentes fuentes.
Usamos datos de mtcars como conjunto de datos de demostración. Comenzamos estandarizando los datos para que las variables sean comparables:
Se puede utilizar la función R heatmap() incorporada [en el paquete de estadísticas]. Un formato simplificado es:
#Es posible especificar la paleta de colores usando el argumento col, la cual puede ser definida de la siguiente manera:
#Usando custom colors
col<- colorRampPalette(c("red", "white", "blue"))(256)
#Usando la paleta de color RColorBrewer
library("RColorBrewer")
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
# Usar RColorBrewer color palette names
library("RColorBrewer")
col <- colorRampPalette(brewer.pal(10, "RdYlBu"))(256)
heatmap(df, scale = "none", col = col,
RowSideColors = rep(c("blue", "pink"), each = 16),
ColSideColors = c(rep("purple", 5), rep("orange", 6)))La función heatmap.2() [en el paquete gplots] proporciona muchas extensiones a la función estándar R heatmap() presentada en la sección anterior.
## Warning: package 'gplots' was built under R version 4.3.2
##
## Attaching package: 'gplots'
## The following object is masked from 'package:stats':
##
## lowess
Se pueden utilizar otros argumentos, entre ellos:
• labRow, laboratorio Col
• hclustfun: hclustfun=función(x) hclust(x, método=“ward”)
En el código R anterior, la función bluered() [en el paquete gplots] se usa para generar.Un conjunto de colores que varían suavemente. También puede utilizar las siguientes funciones del generador de colores:
• panel de color (n, bajo, medio, alto)
n: número deseado de elementos de color que se generarán
bajo, medio, alto: colores a utilizar para los valores más bajo, medio y más alto, mid puede omitirse.
• rojoverde(n), verderojo(n), azulrojo(n) y rojoazul(n)
Primero, instale el paquete pheatmap: install.packages(“pheatmap”); luego escribe esto:
## Warning: package 'pheatmap' was built under R version 4.3.2
Hay argumentos disponibles para cambiar la métrica de agrupación predeterminada (“euclidiana”) y el método (“completo”). También es posible anotar filas y columnas utilizando variables de agrupación.
El paquete dendextend se puede utilizar para mejorar funciones de otros paquetes. Los datos de mtcars se utilizan en las siguientes secciones. Comenzaremos definiendo el orden y la apariencia de las filas y columnas usando dendextend. Estos resultados se utilizan en otras funciones de otros paquetes.
library(dendextend)
# ordenar por filas
Rowv <- mtcars %>% scale %>% dist %>% hclust %>% as.dendrogram %>%
set("branches_k_color", k = 3) %>% set("branches_lwd", 1.2) %>%
ladderize
# Ordenar por columnas
Colv <- mtcars %>% scale %>% t %>% dist %>% hclust %>% as.dendrogram %>%
set("branches_k_color", k = 2, value = c("orange", "blue")) %>%
set("branches_lwd", 1.2) %>%
ladderizeComplexHeatmap es un paquete R/bioconductor, desarrollado por Zuguang Gu, que proporciona una solución flexible para organizar y anotar múltiples mapas de calor. También permite visualizar la asociación entre diferentes datos de diferentes fuentes.
Puedes diseñar un heatmap simple de la siguiente manera:
#install.packages("ComplexHeatmap")
#install.packages("devtools")
#devtools::install_github("jokergoo/ComplexHeatmap")
library(ComplexHeatmap)## Loading required package: grid
## ========================================
## ComplexHeatmap version 2.15.4
## Bioconductor page: http://bioconductor.org/packages/ComplexHeatmap/
## Github page: https://github.com/jokergoo/ComplexHeatmap
## Documentation: http://jokergoo.github.io/ComplexHeatmap-reference
##
## If you use it in published research, please cite either one:
## - Gu, Z. Complex Heatmap Visualization. iMeta 2022.
## - Gu, Z. Complex heatmaps reveal patterns and correlations in multidimensional
## genomic data. Bioinformatics 2016.
##
##
## The new InteractiveComplexHeatmap package can directly export static
## complex heatmaps into an interactive Shiny app with zero effort. Have a try!
##
## This message can be suppressed by:
## suppressPackageStartupMessages(library(ComplexHeatmap))
## ========================================
## ! pheatmap() has been masked by ComplexHeatmap::pheatmap(). Most of the arguments
## in the original pheatmap() are identically supported in the new function. You
## can still use the original function by explicitly calling pheatmap::pheatmap().
##
## Attaching package: 'ComplexHeatmap'
## The following object is masked from 'package:pheatmap':
##
## pheatmap
Heatmap(df,
name = "mtcars", #title of legend
column_title = "Variables", row_title = "Samples",
row_names_gp = gpar(fontsize = 7) # Text size for row names
)Para especificar colores personalizados, debe utilizar la función color Ramp2() [paquete circular], de la siguiente manera:
install.packages(RcolorBrewer)
## Warning: package 'circlize' was built under R version 4.3.2
## ========================================
## circlize version 0.4.15
## CRAN page: https://cran.r-project.org/package=circlize
## Github page: https://github.com/jokergoo/circlize
## Documentation: https://jokergoo.github.io/circlize_book/book/
##
## If you use it in published research, please cite:
## Gu, Z. circlize implements and enhances circular visualization
## in R. Bioinformatics 2014.
##
## This message can be suppressed by:
## suppressPackageStartupMessages(library(circlize))
## ========================================
##
## Attaching package: 'circlize'
## The following object is masked from 'package:igraph':
##
## degree
mycols <- colorRamp2(breaks= c(-2,0, 2),
color= c("green", "white", "red"))
Heatmap(df,name="mtcars", col= mycols)
#Usando la paleta de color deRColorBrewer
library("circlize")
library("RColorBrewer")
Heatmap(df, name = "mtcars",
col = colorRamp2(c(-2, 0, 2), brewer.pal(n=3, name="RdBu")))
#Modificación de la apariencia de dendogramas usando la función color_branches()
library(dendextend)
row_dend = hclust(dist(df)) # row clustering
col_dend = hclust(dist(t(df))) # column clustering
Heatmap(df, name = "mtcars",
row_names_gp = gpar(fontsize = 6.5),
cluster_rows = color_branches(row_dend, k = 4),
cluster_columns = color_branches(col_dend, k = 2))En la sección 10.8.2, la división del mapa de calor por filas se aborda mediante dos enfoques: el uso del algoritmo k-means o una variable de agrupación. Cuando se opta por k-means, es crucial emplear la función set.seed() para garantizar la reproducibilidad precisa de los resultados en momentos posteriores. Para dividir el dendrograma utilizando k-medias, se recomienda escribir el código correspondiente.
Para dividir por una variable de agrupación, utilice el argumento dividir. En el siguiente ejemplo, usaremos los niveles de la variable de factor cyl [en el conjunto de datos de mtcars] para dividir el mapa de calor por filas. Recuerde que la columna cyl corresponde al número de cilindros.
Tenga en cuenta que la división también puede ser una división de las filas del mapa de calor en el marco de datos en el que haya diferentes combinaciones de niveles.
La clase HeatmapAnnotation se utiliza para definir anotaciones en filas o columnas. Para el siguiente ejemplo, transpondremos nuestros datos para tener las observaciones en columnas y las variables en filas.
El vector, que contiene valores discretos o continuos, se utiliza para anotar filas o columnas. Usaremos las variables cualitativas cyl (niveles = “4”, “5” y “8”) y am (niveles = “0” y “1”), y la variable continua mpg para anotar columnas. definido de la siguiente manera:
Para cada una de estas 3 variables, hay colores personalizados.
annot_df <- data.frame(cyl =mtcars$cyl, am= mtcars$am, mpg = mtcars$mpg)
col=list(cyl = c("4"= "green", "6"="gray", "8"="darkred"),
am=c("0"= "yellow", "1"="orange"),
mpg= circlize::colorRamp2(c(17,25),
c("lightblue", "purple")) )En esta sección veremos cómo combinar mapas de calor y algunos gráficos básicos para mostrar la distribución de datos. Para gráficos de anotaciones simples, se pueden utilizar las siguientes funciones: anno_points(), anno_barplot(), anno_boxplot(), anno_density() y anno_histogram().
A continuación se muestra un ejemplo:
.hist = anno_histogram(df, gp = gpar(fill = "lightblue"))
.density = anno_density(df, type = "line", gp = gpar(col = "blue"))
ha_mix_top = HeatmapAnnotation(
hist = .hist, density = .density,
height = unit(3.8, "cm")
)
# Definir algunos gráficos
.violin = anno_density(df, type = "violin",
gp = gpar(fill = "lightblue"), which = "row")
.boxplot = anno_boxplot(df, which = "row")
ha_mix_right = HeatmapAnnotation(violin = .violin, bxplt = .boxplot,
which = "row", width = unit(4, "cm"))
# Combinar la anotación con el heatmap
Heatmap(df, name = "mtcars",
column_names_gp = gpar(fontsize = 8),
top_annotation = ha_mix_top) + ha_mix_rightPara combinar múltiples heatmaps, sigue los pasos que se muestran a continuación.
# Suponiendo que 'df' es tu conjunto de datos
# Heatmap con k-means clustering (km = 3)
ht1 = Heatmap(df, name = "ht1", km = 3, column_names_gp = gpar(fontsize = 9))
# Heatmap adicional
ht2 = Heatmap(df, name = "ht2",
col = circlize::colorRamp2(c(-2, 0, 2), c("green", "white", "red")),
column_names_gp = gpar(fontsize = 9))
# Combine los dos mapas de calor
combined_heatmap = ht1 %v% ht2En los datos de expresión genética, las filas son genes y las columnas son muestras. Se puede adjuntar más información sobre los genes después del mapa de calor de expresión, como la longitud del gen y el tipo de genes.
expr <- readRDS(paste0(system.file(package = "ComplexHeatmap"),
"/extdata/gene_expression.rds"))
mat <- as.matrix(expr[, grep("cell", colnames(expr))])
type <- gsub("s\\d+_", "", colnames(mat))
ha = HeatmapAnnotation(
df = data.frame(type = type),
annotation_height = unit(4, "mm")
)
Heatmap(mat, name = "expression", km = 5, top_annotation = ha,
show_row_names = FALSE, show_column_names = FALSE) +
Heatmap(expr$length, name = "length", width = unit(5, "mm"),
col = circlize::colorRamp2(c(0, 100000), c("white", "orange"))) +
Heatmap(expr$type, name = "type", width = unit(5, "mm")) +
Heatmap(expr$chr, name = "chr", width = unit(5, "mm"),
col = circlize::rand_color(length(unique(expr$chr))))## There are 23 unique colors in the vector `col` and 23 unique values in
## `matrix`. `Heatmap()` will treat it as an exact discrete one-to-one
## mapping. If this is not what you want, slightly change the number of
## colors, e.g. by adding one more color or removing a color.
También es posible visualizar alteraciones genómicas e integrar diferentes niveles moleculares (expresión génica, metilación del ADN,…).
En R, puedes crear mapas de calor utilizando la función base heatmap.2() del paquete gplots para opciones básicas y control sobre parámetros gráficos. También, la función heatmap() en el mismo paquete es una alternativa básica.
Para mapas de calor más complejos y versátiles, el paquete Complex Heatmap proporciona la función Heatmap(). Esta opción es especialmente útil en campos como la genómica, permitiendo la creación, anotación y organización de mapas de calor más elaborados. La elección entre estas funciones dependerá de la complejidad y control deseados en la visualización.