UNIVERSIDAD DE EL SALVADOR
FACULTAD DE CIENCIAS ECONOMICAS
ESCUELA DE ECONOMIA
Materia: Métodos para el análisis económico
Docente: Carlos Ademir Pérez Alas
Grupo teórico: 3
Laboratorio 2: Análisis de Clúster
Integrantes:
| Apellidos | Nombres | DUE |
|---|---|---|
| Escolán Chávez | Diana Alejandra | EC19003 |
| García Cabrera | Bryan Alexander | GC17011 |
Ciclo: II-2021
Fecha: Lunes 22 de noviembre, 2021
Ciudad Universitaria, San Salvador, El Salvador
Indicación: Explique en que consiste el análisis de conglomerados.
El análisis de clúster (que también recibe el nombre de análisis de segmentación) es un método estadístico exploratorio para el procesamiento de datos, este consiste en organizar los elementos en grupos o “clústeres” basándose en qué tan similares son estos elementos entre sí. Es decir se identifican estructuras presentes en la data.
Figura 1: Comparación entre data original y data agrupada por análisis de clúster. Fuente: Miro Medium.
> Este análisis es un algoritmo de aprendizaje no supervisado, lo que significa que no sabe cuántos conglomerados existen en los datos antes de ejecutar el modelo. A diferencia de muchos otros métodos estadísticos, el análisis de conglomerados se utiliza normalmente cuando no se realizan suposiciones sobre las posibles relaciones dentro de los datos. Proporciona información sobre dónde existen asociaciones y patrones en los datos, pero no cuáles podrían ser o qué significan. (Qualtrics, 2021)
Aplicaciones.
El análisis de conglomerados se utiliza con fines de clasificación de elementos o sujetos en grupos que presentan características similares. A continuación se presentan algunas áreas de aplicación.
Educación: Suelen tomarse en cuenta aptitudes especiales, perfiles psicológicos y rendimiento con el objeto de caracterizar a grupos de estudiantes para emplear técnicas de aprendizaje adecuadas.
Urbanismo: Identificación de zonas a partir del valor de la vivienda, sus características en términos de construcción, ubicación, entre otros.
Estudios de mercados: El objeto es identificar el comportamiento, perfil y necesidades de los consumidores.
Indicación: Elaborar un cuadro comparativo que incluya información sobre el análisis de cluster, técnicas disponibles, ventajas y desventajas.
Nota: La tabla debe ser generada en Rmarkdown.
Para ello se utilizan las siguientes librerías: Pander (Daróczi and Tsegelskyi, 2021), kableExtra (Zhu, 2021) y dplyr (Wickham, François, Henry and Müller, 2021).
library(pander)
library(kableExtra)
library(dplyr)
tabla <- data.frame(
Análisis_de_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.",
"No jerárquico: Su objetivo es encontrar una
agrupación de elementos que maximice o minice
un criterio de evaluación."),
Técnicas_Disponibles = c(
"* Aglomerativas.\
\n* Divisivas.",
"* Algoritmos de partición: k-means, K-mediodes o PAM, CLARA.\
\n* Análisis basados en la densidad.\
\n* Análisis basados en cuadrículas.\
\n* Análisis basados en modelos."),
Ventajas = c("* Genera una estructura muy ilustrativa. Es fácil decidir
el número de conglomerados observando el dendrograma.\
\n* Fácil de implementar, leer y comprender." ,
"* Es comparativamente más confiable que la agrupación jerárquica.\
\n* Es comparativamente más rápido que el agrupamiento jerárquico.\
\n* Puede funcionar mejor que la agrupación jerárquica incluso cuando existe
un error.\
\n* Con una gran cantidad de variables, K-Means puede ser computacionalmente
más rápido que el agrupamiento jerárquico (si K es pequeño).\
\n* Es una técnica relativamente estable."),
Desventajas = c("* No es posible deshacer el paso anterior.\
\n* Complejidad de tiempo: no apto para grandes conjuntos de datos.\
\n* El orden de los datos tiene un impacto en los resultados finales.\
\n* Muy sensible a valores atípicos.\
\n* Todos los enfoques para calcular la similitud entre clústeres tienen
sus propias desventajas.",
"* Puede ser díficil predecir el número de grupos (valor de k).\
\n* Difícil lectura y comprensión en comparación con los clústeres
jerárquicos.\
\n* El orden de los datos tiene un fuerte impacto en los resultados finales.\
\n* Sensibilidad a las escalas: Los datos normalizados cambia el
resultado totalmente.\
\n* Las semillas tienen un fuerte impacto en los resultados.")
)
pander::pander(tabla, keep.line.breaks = TRUE,
style = 'grid',
justify = 'left',
col.names = c("Análisis de Clúster",
"Técnicas disponibles", "Ventajas", "Desventajas"))| Análisis de Clúster | Técnicas disponibles |
|---|---|
| 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. |
|
| No jerárquico: Su objetivo es encontrar una agrupación de elementos que maximice o minice un criterio de evaluación. |
|
| Ventajas | Desventajas |
|---|---|
|
|
|
|
Fuente: Elaboración propia en base a Patrola y University of Ferrara.
Indicación: 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.
El desarrollo de este contenido ha tomado de base a (Kassambara, 2017) , (Bonnini and Mini, 2019), y (De la Fuente).
Llamadas por sus siglas en inglés HCA (Hierarchical Cluster Analysis). En este caso, lo que se pretende es la agrupación de los elementos según la similitud que exista entre ellos. Dicha agrupación lleva a su base un criterio que permite generar una jerarquía de divisiones en la serie de datos.
Es conocida por sus siglas en inglés AGNES (Agglomerative Nesting), en este método, se parte de clasificar cada observación en un clúster, luego se van agrupando los conglomerados creados buscando maximizar la mayor similitud existente entre ellos, así, se van fusionando los que posean mayor similitud hasta que todas las observaciones forman parte de un solo clúster. Kassambara (2017), compara las técnicas jerárquicas con la estructura de un árbol. Para esta técnica, los clústers generados al inicio son representados con una hoja, que llegan a formar parte de un solo árbol, siendo este el clúster final.
Para implementar esta técnica en RStudio, se utiliza la función agnes, que forma parte del paquete Cluster (Maechler et. al., 2021). Dentro del objeto que se crea con emplear agnes() se destaca la obtención del coeficiente de aglomeración y la clasificación que corresponde a cada observación. A su vez,la información obtenida puede emplearse para la representación gráfica, por medio de un dendograma.
La sintaxis para utilzarla es la siguiente: \[agnes(X, stand, metric, method)\] Donde:
X = Conjunto de datos, que puede ser un objeto tipo matriz o data frame, en el que las filas corresponden a las observaciones y las columnas a las variables.
Stand = Valor lógico, al seleccionar TRUE, la información de X será estandarizada por cada variable antes de calcular la disimilitud.
Metric = Se especifica la métrica que se utilizará para calcular la disimilitud entre las observaciones, se recomienda “euclidean”, para utilizar la distancia Euclidiana.
Method = En este argumento se define el método de agrupación. Uno de los más comunes es “ward”, que hace referencia al Método de varianza mínima de Ward.
Luego, para realizar el dendograma, se utiliza la función fviz_dend() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_dend(objeto, cex, k)\] Donde:
Nombre_objeto = Es el objeto en el que se ha guardado lo aplicado con la función agnes().
cex = Tamaño de las etiquetas de las observaciones, se sugiere un valor de 0.6.
k = El número de grupos en que se cortará el dendograma.
Conocida por sus siglas en inglés DIANA (Divise Analysis), esta técnica desarrolla el proceso inverso a la técnica aglomerativa, puesto que, su punto de partida es un gran clúster en el que están incluidas todas las observaciones, y a través pasos iterativos, se va segmentando, partiendo del primer conglomerado y luego los conglomerados más heterogéneos, hasta que cada observación quede asignado en su clúster correspondiente. Por tanto, este método es recomendado para clústers grandes.
Esta técnica en RStudio puede aplicarse con la función diana(), incluída en el paquete Cluster (Maechler et. al., 2021), cuya sintaxis para utilzarla es la siguiente: \[diana(X, stand, metric)\]
Donde:
X = Conjunto de datos, debe ser un objeto tipo matriz o data frame, en el que las filas corresponden a las observaciones y las columnas a las variables.
Stand = Valor lógico, al seleccionar TRUE, la información de X será estandarizada por cada variable antes de calcular la disimilitud.
Metric = Se especifica la métrica que se utilizará para calcular la disimilitud entre las observaciones, se recomienda “euclidean”, para utilizar la distancia Euclidiana.
Posteriormente, para realizar la demostración gráfica, se utiliza la función fviz_dend() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_dend(objeto, cex, k)\]
Donde:
Nombre_objeto = Es el objeto en el que se ha guardado lo aplicado con la función diana().
cex = Tamaño de las etiquetas de las observaciones, se sugiere un valor de 0.6.
k = El número de grupos en que se cortará el dendograma.
Conocidas por sus siglas en inglés NHCA (Non Hierarchical Cluster Analysis). Estos métodos de agrupamiento buscar dividir el conjunto de observaciones en un número de clústers previamente definidos por el investigador. En este caso, las observaciones se van asignando a los conglomerados de forma directa, contrario a los métodos jerárquicos, en el que antes de la agrupación, se compara la similitud entre casos para luego proceder a la formación de los clústers.
Es la técnica más utilizada dentro del análisis de clúster utilizada por primera vez por J. MacQueen en 1967; en la cual, se parte seleccionando aleatoriamente k elementos (siendo k el número de clústers a obtener, definidos por el investigador), los cuales serán los centros medios o centroides iniciales del conglomerado. Luego, el algoritmo asigna el resto de observaciones a los centroides más cercanos, por medio de la distancia Euclideana. Este proceso hará que se calcule un nuevo centroide para cada clúster y por tanto, si procede, una reasignación de los demás elementos a otros clústers. Cada conglomerado se representa por el valor medio de sus observaciones.
El punto de partida es especificar el número de clústers, representado por k. Como se definía anteriormente, antes de aplicar la ténica debe especificarse el número de clústers, representado por k. Ya habiendo definido k, se procede a desarrollar el proceso en RStudio por medio de la función kmeans(), incluída en el paquete Stats (R Core Team, 2021), cuya sintaxis se muestra a continuación:
\[kmeans(X, centers, iter.max, nstart)\] Donde:
X = Data original, el cual debe ser de tipo matriz.
Centers = Número de clústers.
Iter.max = El número máximo de iteraciones permitidas, se recomienda realizar 10 iteraciones.
Nstart = El número de conjuntos aleatorios deben formarse para cada centroide.
Para visualizar el resultado de aplicar la técnica, se utiliza la función fviz_cluster() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_cluster(objeto, data, palette, ellipse.type, star.plot, repel, ggtheme)\] Donde:
Objeto = El objeto en el que se ha guardado lo ejecutado con la función kmeans().
Data = La matriz de información original normalizada.
Palette = El vector de colores para los k clústers creados.
Ellipse.type = Tipo de marco a utilizar, se recomienda “euclid”, para mostrar una concentración de ellipse.
Star.plot = Valor lógico. Al seleccionar TRUE, se añaden los segmentos creados para cada centroide.
Repel = Valor lógico. Al seleccionar TRUE, se evita el sobretrazado de las etiquetas de las observaciones.
Ggtheme = El tipo de tema del gráfico. Por defecto elige theme_pubr()
Conocida por sus siglas en inglés PAM (Partitioning Around Medoids), técnica aportada por Kaufman y Rousseeuw en 1990. Cada clúster obtenido por este método está representado por un meodide, el cual posee la característica que su desimilitud entre él y el resto de observaciones del conglomerado es mínima, asegurando así mayor robustez en esta técnica, superando un problema que adolece K-means, que es altamente sensible a datos atípicos.
Para determinar el número de clústers, representado por k, puede estimarse en RStudio por medio de la función fviz_nbclust(), que se encuentra en el paquete factoextra (Kassambara and Mundt, 2020); y a su vez se requiere cargar el paquete cluster (Maechler et. al., 2021), para definir un argumento de la función. La sintaxis a seguir es la siguiente:
\[fviz\_nbclust(data, técnica, method)+(theme\_classic())\]
Donde:
Data = La matriz de información normalizada.
Técnica = El método de clúster a aplicar, en este caso, pam.
Method = El método que se utilizará para obtener el número óptimo de clústers. Puede utilizarse “silhouette”.
Theme_classic() = El tema a elegir para mostrar el gráfico.
Ya definido k, se procede a desarroollar el proceso en RStudio, puede realizarse por medio de la función pam(), incluída en el paquete Cluster (Maechler et. al., 2021), cuya sintaxis se muestra a continuación:
\[pam(X, k, metric, stand)\] Donde:
X = Matriz de información o data frame original, el cual puede ser también una matriz de disimilitud.
K = Número de clústers.
Metric = La métrica a utilizar para calcular la distancia. Puede elegirse entre distancia Euclideana o Manhattan.
Stand = Valor lógico, debe seleccionarse FALSE en caso X sea una matriz de disimilitud, caso contrario, seleccionar TRUE para normalizar la data y calcular la matriz de disimilitud.
Para presentar los resultados de manera visual, se utiliza la función fviz_cluster() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_cluster(objeto, palette, ellipse.type, repel, ggtheme)\] Donde:
Objeto = El objeto en el que se ha guardado lo ejecutado con la función pam().
Palette = El vector de colores para los k clústers creados.
Ellipse.type = Tipo de marco a utilizar.
Repel = Valor lógico. Al seleccionar TRUE, se evitan los excesos de etiquetas.
Ggtheme = El tipo de tema del gráfico. Por defecto elige theme_pubr()
Su nombre se deriva de sus siglas en inglés CLARA (Clustering Large Applications) creada por Kaufman y Rousseeuw en 1990. Se considera una extensión de K-mediodes, la cual su algoritmo está desarrollado para conjuntos de datos de grandes cantidades de observaciones, reduciendo el tiempo de procesamiento del cálculo en los ordenadores. Esto se consigue por medio de la segmentación de las observaciones en muestras de mismo tamaño, y con la técnica PAM se calculan la cantidad de mediodes óptimos para cada muestra. La calidad de dichos mediodes se asegura con la media de disimilitud entre cada observación del clúster y su medoide. Este algoritmo se repite el número de veces definidas hasta lograr los mediodes con mínima media de disimilitud.
Para estimar el número óptimo de clústers, representado por k, puede realizarse de la misma forma que se presentó para el cálculo de k en la técnica K-medoides, cuya sintaxis se muestra a continuación
\[fviz\_nbclust(data, técnica, method)+(theme\_classic())\]
Donde:
Data = La matriz de información normalizada.
Técnica = El método de clúster a aplicar, en este caso, clara.
Method = El método que se utilizará para obtener el número óptimo de clústers. Puede utilizarse “silhouette”.
Theme_classic() = El tema a elegir para mostrar el gráfico.
Estimado k, se procede a desarrollar el proceso en RStudio, puede realizarse por medio de la función clara(), que pertenece al paquete Cluster (Maechler et. al., 2021), cuya sintaxis se muestra a continuación:
\[cluster(X, k, metric, stand, samples, pamLike)\] Donde:
X = Matriz de información o data frame original.
K = Número de clústers.
Metric = La métrica a utilizar para calcular la disimilitud entre observaciones. Puede elegirse entre distancia Euclideana o Manhattan.
Stand = Valor lógico, debe seleccionarse FALSE en caso las data original ya esté normalizada, caso contrario, seleccionar TRUE para normalizar la data antes de calcular las disimilitudes.
PamLike = Valor lógico, debe seleccionarse FALSE en caso las data original ya esté normalizada, caso contrario, seleccionar TRUE para normalizar la data antes de calcular las disimilitudes.
El resultado puede presentarse en un gráfico de dispersión por medio de la función fviz_cluster() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_cluster(objeto, palette, ellipse.type, geom, pointsize, ggtheme)\] Donde:
Objeto = El objeto en el que se ha guardado lo desarrollado con la función clara().
Palette = El vector de colores para los k clústers creados.
Ellipse.type = Tipo de marco a utilizar.
Geom = Muestra el tipo de geometría para utilizar en la presentación del gráfico. Es recomendable usar “point”.
Pointsize = Indica el tamaño de los puntos, puede designarse un tamaño de 1.
Ggtheme = El tipo de tema del gráfico. Por defecto elige theme_pubr()
Esta técnica de clúster, permite la formación de conglomerados tomando de base los espacios intensivos de datos, es decir, las regiones que presenten la mayor densidad en la región de los datos, serán consideradas los clústers. Esto se muestra gráficamente como zonas con mayor densidad de puntos.
Una de las técnicas más usadas de este tipo es la Agrupación espacial basada en densidad de aplicaciones con ruido, más conocida por sus siglas en inglés DBSCAN (Density-Based Spatial Clustering and Application with Noise), creado por Ester et. al. en 1996, que permite la creación de clústers sin importar su tipo, teniendo en cuenta un conjunto de datos que presente ruido y valores atípicos.
De las grandes ventajas que se tiene es que la misma técnica define el número óptimo de clústers, por lo que no es necesario hacer un paso previo para su cálculo, por lo que se procede de una vez a desarrollar el proceso en RStudio, puede realizarse por medio de la función DBSCAN(), que pertenece al paquete fpc (Hennig, 2020), cuya sintaxis se muestra a continuación:
Primero, se escribe el siguiente código para fijar la semilla: \[set.seed(123)\]
Luego, se ejecuta la sintaxis que para aplicar la técnica: \[dbscan(X, eps, MinPts)\] Donde:
X = Matriz de información o data frame original, el cual puede ser también una matriz de disimilitud.
eps = Distancia de alcance. (Kassambara, 2017) recomienda asignar un valor de 0.15.
MinPts = Número mínimo de puntos de alcanzabilidad, (Kassambara, 2017) recomienda asignar un valor de 5.
El resultado puede presentarse de forma visual con la función fviz_cluster() incluída en el paquete factoextra (Kassambara and Mundt, 2020), con la siguiente sintaxis:
\[fviz\_cluster(objeto, data, stand, ellipse, show.clust.cent, geom, palette, ggtheme)\] Donde:
Objeto = El objeto en el que se ha guardado lo desarrollado con la función dbscan().
Data = La matriz de información original.
Stand = Valor lógico, TRUE implica que la data es estandarizada antes del Análisis de componentes principales.
Ellipse = Valor lógico, TRUE se dibujará el contorno de los puntos de cada clúster.
Show.clust.cent = Valor lógico, TRUE se mostrarán los centros de los clústers.
Geom = Muestra el tipo de geometría para utilizar en la presentación del gráfico. Es recomendable usar “point”.
Palette = El vector de colores para los k clústers creados.
Ggtheme = El tipo de tema del gráfico. Por defecto elige theme_pubr()
Esta técnica toma en consideración las celdas en lugar de los datos. Debido a esta característica, los algoritmos de agrupación en clústeres basados en cuadrículas parecen ser generalmente más eficaz que todos los algoritmos de agrupamiento computacional.
Esta técnica, introducida por C. Fraley y A. Raftery entre el 2002 y el 2012, se considera que las observaciones provienen de una distribución que resulta de la mezcla de dos o más conglomerados, es decir, que provienen de una mezcla de densidad. Este modelo realiza una asignación, donde cada observación posee cierta probabilidad de pertenecer a cada clúster.
En el proceso de este método, se deben analizar tres parámetros para el modelo, que pueden estimarse mediante el algoritmo de maximización de expectativas (EM). Las características geométricas (forma, volumen y orientación) se obtienen mediante la matriz de covarianza.
El mejor modelo se selecciona mediante el Criterio de información bayesiano BIC, por sus siglas en inglés (Bayesian Information Criterion), el cual un valor grande supone evidencia significativa para el modelo elegido.
Para aplicar esta técnica en RStudio, se comienza con hacer un gráfico de dispersión para tener una aproximación de la cantidad de clústers posibles a encontrar, así como un acercamiento a determinar sus características geométricas, esto es posible con la función ggscatter, del paquete ggpubr (Kassambara, 2020). Su sintaxis es la siguiente:
\[ggscatter(data, x, y) + geom_density2d()\] Donde:
Data = Base de datos, debe ser tipo data frame.
X, y = Variables a graficar.
Geom_density2d() = Para agregar una representación gráfica de densidad 2D.
Luego de la representación gráfica de la data, se procede a ejecutar esta técnica con la función Mclust, de la librería mclust (Scrucca et. al., 2016), cuya sintaxis se muestra a continuación:
\[Mclust(data)\] Donde:
Para mostrar los resultados, debe imprimirse el resumen de los resultados obtenidos:
\[Summary(objeto\_Mclust)\] Mientras que para presentar gráficamente los elementos de esta técnica, se utiliza las siguientes sintaxis, con la fórmula fviz_cluster() incluída en el paquete factoextra (Kassambara and Mundt, 2020):
Para mostrar los valores BIC, se emplea la siguiente sintaxis:
\[fviz\_mclust(objeto, "BIC", palette)\] Donde:
Objeto = Objeto en que fue guardado el proceso realizado con la función Mclust().
“BIC” = Graficar los valores del Criterio de información bayesiano, BIC.
Palette = Para seleccionar la paleta de colores.
Para mostrar la clasificación de las observaciones en los clústers, se usa la siguiente sintaxis:
\[fviz\_mclust(objeto, "classification", geom, pointsize, palette)\]
Donde:
Objeto = Objeto en que fue guardado el proceso realizado con la función Mclust().
“Classification” = Para graficar la clasificación de las observaciones.
Geom = Determina la figura geométrica para representar las observaciones.
Pointsize = Para seleccionar el tamaño de los puntos.
Palette = Para seleccionar la paleta de colores.
Finalmente, para graficar incertidumbre de la clasificación de las observaciones en los clústers, se usa la siguiente sintaxis:
\[fviz\_mclust(objeto, "uncertainty", palette)\]
Donde:
Objeto = Objeto en que fue guardado el proceso realizado con la función Mclust().
“Uncertainty” = Para graficar la incertidumbre de la clasificación de las observaciones.
Palette = Para seleccionar la paleta de colores.
Indicación: Del texto: Kassambara, A. (2017). Practical Guide to Cluster Analysis in R: Unsupervised Machine Learning (Multivariate Analysis) (1st ed.) Desarrolle los ejemplos presentados en los capítulos: 4,5,6,7,8,9
Carga de datos
data("USArrests") # Cargando el data set de R base
df <- scale(USArrests) # Usando el argumento scale
# Visualizando las primeras 3 filas del set de datos
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
Estimando el número óptimo de clusters
library(factoextra)## Warning: package 'factoextra' was built under R version 4.0.5
## Loading required package: ggplot2
## Warning: package 'ggplot2' was built under R version 4.0.5
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_nbclust(df, kmeans, method = "wss") +
geom_vline(xintercept = 4, linetype = 2)El doblez en el gráfico es un indicador para determinar el número óptimo de clusters.
Computación de clústers de k-medios
Utilizando el argumento de set.seed para generar números aleatorios:
# Cuando k = 4
set.seed(123)
km.res <- kmeans(df, 4, nstart = 25)
# Mostrando los resultados
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 del conglomerado (1 a 4) y las columnas son variables • el vector de agrupación: un vector de números enteros (de 1: k) que indica la agrupación a que se asigna a cada punto
Obteniendo la medida de cada variable por cluster usando la data original
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
En caso de querer agregar las clasificaciones puntuales a la data original:
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
Accesando a los resultados de una función k-means
# Número de cluster de las observaciones
head(km.res$cluster, 4)## Alabama Alaska Arizona Arkansas
## 1 4 4 1
# Tamaño del cluster
km.res$size## [1] 8 13 16 13
# Media de los clusters
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
Visualizando cluster de k-medios
fviz_cluster(km.res, data = df,
palette = c("darkslateblue", "#00AFBB", "#E7B800", "#FC4E07"),
ellipse.type = "euclid", # Concentration ellipse
star.plot = TRUE, # Agregar segmentos de los centroides a los elementos
repel = TRUE, # Evitar exceso de etiquetas
ggtheme = theme_minimal()
)# Retomando el dataframe 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
Caragando los paquetes cluster y factoextra
Estimando el número óptimo de clústers
library(cluster)## Warning: package 'cluster' was built under R version 4.0.5
library(factoextra)
fviz_nbclust(df, pam, method = "silhouette") +
theme_classic()Según este método gráfico, el número óptimo es k = 2.
Computación de PAM en R
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"
La salida muestra: * Los medoides de cada cluster: Una matriz donde las filas corresponden a los medoides y las columnas son las variables. * Vector de agrupación: Un vector de 1:k que indica la agrupación que se asigna a cada observación.
En caso de querer agregar las clasificaciones puntuales a la data original:
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
Accesando a los resultados de una función pam()
Una función pam() contiene a dos elemetos: medoides, objetos que representan a los clusters; agrupaciones, vector que contiene el número de cluster de cada observación.
# Medoides de cluster: Nebraska y New Mexico
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úmero de cluster
head(pam.res$clustering)## Alabama Alaska Arizona Arkansas California Colorado
## 1 1 1 2 1 1
Visualizando clusters PAM
fviz_cluster(pam.res,
palette = c("royalblue3", "violetred3"), # Paleta de color
ellipse.type = "t", # Elipse de concentración
repel = TRUE, # Para evitar el exceso de etiquetas
ggtheme = theme_classic()
)Se parte de generar un dataset aleatorio usando la función set.seed()
set.seed(1234)
# Generar 500 objetos, divididos en 2 clusters.
df <- rbind(cbind(rnorm(200,0,8), rnorm(200,0,8)),
cbind(rnorm(300,50,8), rnorm(300,50,8)))
# Especificar nombres de filas y columnas
colnames(df) <- c("x", "y")
rownames(df) <- paste0("S", 1:nrow(df))
# Visualizando la data
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
Estimando el número óptimo de clusters
library(cluster)
library(factoextra)
fviz_nbclust(df, clara, method = "silhouette")+
theme_classic()Según este método gráfico, el número óptimo es k = 2.
Computación de CLARA en R
clara.res <- clara(df, 2, samples = 50, pamLike = TRUE)
# Mostrar lso 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"
Si se desea agregar las clasificaciones puntuales a la data original:
ddCLARA <- cbind(df, cluster = clara.res$cluster)
head(ddCLARA, 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
Accesando a los resultados de la función clara()
# Medoides
clara.res$medoids## x y
## S121 -1.531137 1.145057
## S455 48.357304 50.233499
# Número de cluster de cada observación
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
Visualizando clusters CLARA
fviz_cluster(clara.res,
palette = c("slateblue3", "turquoise2"), # Paleta de color
ellipse.type = "t", # Elipse de concentración
geom = "point", pointsize = 1,
ggtheme = theme_classic()
)# Retomando el dataframe USArrests
data("USArrests")
# Estandarizando los datos
df <- scale(USArrests)
# Mostrar las 6 primera 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 similaridad
En este aparatado se mide la similaridad entre objetos para decidir cuáles de estos deben ser combinados o divididos. Para la matriz de distancias:
# Matriz de disimilitudx
# df = data estandarizada
res.dist <- dist(df, method = "euclidean")
# Convertir en matriz
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
Enlace
La función de enlace toma la distancia de la información y agrupa pares de objetos en clusters según su similitud.
res.hc <- hclust(d = res.dist, method = "ward.D2")Dendrograma
# cex: Tamaño de etiqueta
library("factoextra")
fviz_dend(res.hc, cex = 0.5)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Verificar el árbol del cluster
Una vez vinculados los objetos de un conjunto de datos en un árbol de clúster jerárquico, deben evaluarse que las distancias ( alturas) en el árbol reflejan las distancias originales precisamente. Los objetos en el árbol deben mostrar una fuerte correlación con las distancias entre los objetos de la matriz de distancia original.
# Distancia cophenética
res.coph <- cophenetic(res.hc)
# Correlación ente la distancia cophenética y la distancia original
cor(res.dist, res.coph)## [1] 0.6975266
Utilizando el método de enlace o vinculación promedio se evalúa la solución del agrupamiento
res.hc2 <- hclust(res.dist, method = "average")
cor(res.dist, cophenetic(res.hc2))## [1] 0.7180382
Este resultado muestra que el método de enlace distinto genera un árbol más representativo de las distancias originales.
Cortar el dendrograma en diferentes grupos
Dado que no se tiene un valor de k se porcede a cortar el árbol jerárquico a cierta altura para dividir la data en clusters. Para ello se utiliza la función cutree() a partir de la función hclust().
# 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 elementos en cada cluster
table(grp)## grp
## 1 2 3 4
## 7 12 19 12
# Obtener los nombres de los miembros del cluster 1
rownames(df)[grp == 1]## [1] "Alabama" "Georgia" "Louisiana" "Mississippi"
## [5] "North Carolina" "South Carolina" "Tennessee"
# Cortar en 4 grupos y colorear por grupo
fviz_dend(res.hc, k = 4, # Cortar en 4 grupos
cex = 0.5, # Tamaño de etiqueta
k_colors = c("cyan4", "violetred1", "navyblue", "mediumpurple1"),
color_labels_by_k = TRUE, # Color de etiqueta por grupo
rect = TRUE # Agregar rectángulo alrededor de los grupos
)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
fviz_cluster(list(data = df, cluster = grp),
palette = c("cyan4", "violetred1", "navyblue", "mediumpurple1"),
ellipse.type = "convex",
repel = TRUE,
show.clust.cent = FALSE, ggtheme = theme_minimal())Paquete Cluster de R
Este paquete facilita el análisis de cluster, para ello se utilizan las funciones agnes() y diana().
library("cluster")
# Anidamiento aglomerativo (agrupamiento jerárquico)
res.agnes <- agnes(x = USArrests, # Matriz de datos
stand = TRUE, # Estandarizar la matriz
metric = "euclidean", # Métrica para matriz de distancia
method = "ward" # Método de enlace
)
# Agrupación de análisis visual
res.diana <- diana(x = USArrests, # Matriz de datos
stand = TRUE, # Estandarizar los datos
metric = "euclidean" # Métrica para matriz de distancia
)
# Visualizando el resultado
fviz_dend(res.agnes, cex = 0.6, k = 4)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Aplicación de agrupaciones jerárquicas a análisis de genes de datos de expresión
Es una premisa de exploración de los datos.
En este capítulo se comparan dedrogramas usando el paquete dendextend.
# Preparando los datos
data("USArrests") # Cargando el data set de R base
df <- scale(USArrests)
# Subset que contiene 10 filas
set.seed(123)
ss <- sample(1:50, 10)
df <- df[ss,]Comparando dendrogramas
Se parte de una lista de dos dendrogramas tomando en cuenta las agrupaciones jerárquicas usando métodos distintos de enlace (average y sala.D2)
library(dendextend)## Warning: package 'dendextend' was built under R version 4.0.5
# Compute distance matrix
res.dist <- dist(df, method = "euclidean")
# Compute 2 hierarchical clusterings
hc1 <- hclust(res.dist, method = "average")
hc2 <- hclust(res.dist, method = "ward.D2")
# Create two dendrograms
dend1 <- as.dendrogram (hc1)
dend2 <- as.dendrogram (hc2)
# Create a list to hold dendrograms
dend_list <- dendlist(dend1, dend2)Comparación visual de los dendrogramas
Para ello se utiliza la función tanglegram()
tanglegram(dend1, dend2)Para personalizar la salida anterior:
tanglegram(dend1, dend2,
highlight_distinct_edges = FALSE, # Desactiva las líneas punteadas
common_subtrees_color_lines = FALSE, # Desactiva las líneas de color
common_subtrees_color_branches = TRUE, # Color para las ramas
main = paste("entanglement =", round(entanglement(dend_list), 2))
)Matriz de correlación entre una lista de dendrogramas
La función cor.dendlist () calcula la matriz de correlación “Baker” o “Cophenetic” entre una lista de árboles. El valor ronda entre -1 y 1. Un valor cercano a 0 significa que los dos árboles no son estadísticamente similares.
# Matriz de correlación cofenética
cor.dendlist(dend_list, method = "cophenetic")## [,1] [,2]
## [1,] 1.0000000 0.9925544
## [2,] 0.9925544 1.0000000
# Matriz de correlación de Baker
cor.dendlist(dend_list, method = "baker")## [,1] [,2]
## [1,] 1.0000000 0.9895528
## [2,] 0.9895528 1.0000000
La correlación entre dos árboles también se puede calcular de la siguiente manera:
# Coeficiente de correlación cofenética
cor_cophenetic(dend1, dend2)## [1] 0.9925544
# BCoeficiente de correlación de Baker
cor_bakers_gamma(dend1, dend2)## [1] 0.9895528
Una alternativa de código:
library(dplyr)
# Crea múltiples dendrogramas encadenando
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
# Calcular matriz de correlación
dend_list <- dendlist("Complete" = dend1, "Single" = dend2,
"Average" = dend3, "Centroid" = dend4)
cors <- cor.dendlist(dend_list)
# Imprimir matriz de correlación
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
# Visualice la matriz de correlación usando el paquete corrplot
library(corrplot)## corrplot 0.90 loaded
corrplot(cors, "pie", "lower")Como se dijo anteriormente, un dendrograma es una representación arbórea de datos creados mediante métodos de agrupación jerárquica.
# Cargar datos
data(USArrests)
# Calcular distancias y agrupamiento jerárquico
dd <- dist(scale(USArrests), method = "euclidean")
hc <- hclust(dd, method = "ward.D2")fviz_dend(hc, k = 4, # Cortar en 4 grupos
cex = 0.5, # Tamaño de etiqueta
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE, # Color de etiqueta por grupo
rect = TRUE, # Agregar rectángulo alrededor de los grupos
rect_border = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
rect_fill = TRUE)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
## Warning in if (color == "cluster") color <- "default": la condición tiene
## longitud > 1 y sólo el primer elemento será usado
Otro formato:
fviz_dend(hc, k = 4,
cex = 0.5,
k_colors = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
color_labels_by_k = TRUE,
ggtheme = theme_gray() # Cambiar tema
)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Formato para oncología clínica:
fviz_dend(hc, cex = 0.5, k = 4,
k_colors = "jco")## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Para un dendrograma horizontal:
fviz_dend(hc, k = 4, cex = 0.4, horiz = TRUE, k_colors = "jco",
rect = TRUE, rect_border = "jco", rect_fill = TRUE)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Dendrograma circular:
fviz_dend(hc, cex = 0.5, k = 4,
k_colors = "jco", type = "circular")## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Dendrograma arbóreo, requiere el paquete igraph.
library(igraph)## Warning: package 'igraph' was built under R version 4.0.5
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:dplyr':
##
## as_data_frame, groups, union
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
fviz_dend(hc, k = 4, k_colors = "jco",
type = "phylogenic", repel = TRUE)Dendrogramas para sets grandes
Hacer zoom al dendrograma:
fviz_dend(hc, xlim = c(1, 20), ylim = c(1, 8))## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Trazar un subárbol de dendrogramas:
# Crear una gráfica de todo el dendrograma y extraer los datos del dendrograma
dend_plot <- fviz_dend(hc, k = 4, # Cortar en 4 grupos
cex = 0.5,
k_colors = "jco"
)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
dend_data <- attr(dend_plot, "dendrogram") # Extraer data del dendrograma
# cortar el dendrograma a una altura h = 10
dend_cuts <- cut(dend_data, h = 10)
# Dos ramas
fviz_dend(dend_cuts$upper)## Warning in min(-diff(our_dend_heights)): ningún argumento finito para min;
## retornando Inf
## Warning in min(-diff(our_dend_heights)): `guides(<scale> = FALSE)` is
## deprecated. Please use `guides(<scale> = "none")` instead.
# Mostrar el dendrograma completo
print(dend_plot)# Graficar sub árbol 1
fviz_dend(dend_cuts$lower[[1]], main = "Subtree 1")## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
# Graficar sub árbol 2
fviz_dend(dend_cuts$lower[[2]], main = "Subtree 2")## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Graficando árboles circulares:
fviz_dend(dend_cuts$lower[[2]], type = "circular")## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
Manipulando dendrogramas usando dendextend
El paquete dendextend proporciona funciones para cambiar fácilmente la apariencia de un dendrograma y para comparar dendrogramas.
Código estándar para crear un dendrograma:
data <- scale(USArrests)
dist.res <- dist(data)
hc <- hclust(dist.res, method = "ward.D2")
dend <- as.dendrogram(hc)
plot(dend)Código usando pipe:
library(dendextend)
dend <- USArrests[1:5,] %>% # data
scale %>% # Estandarizar
dist %>% # Calcular matriz de distancia
hclust(method = "ward.D2") %>% # Agrupación jerárquica
as.dendrogram # Convertir en dendrograma
plot(dend)Personalizando la función:
library(dendextend)
mycols <- c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07")
dend <- as.dendrogram(hc) %>%
set("branches_lwd", 1) %>% # Ancho de ramas
set("branches_k_color", mycols, k = 4) %>% # Colorear ramas por grupo
set("labels_colors", mycols, k = 4) %>% # Etiquetas de color por grupo
set("labels_cex", 0.5) #
fviz_dend(dend)## Warning: `guides(<scale> = FALSE)` is deprecated. Please use `guides(<scale> =
## "none")` instead.
[1] Difference between Hierarchical and Non Hierarchical Clustering. En-us. jun.. 2020. <URL: https://www.geeksforgeeks.org/difference-between-hierarchical-and-non-hierarchical-clustering/> (visited on 11/10/2021).
[2] Hierarchical cluster analysis. En-us. jun.. 2020. <URL: https://mb3is.megx.net/gustame/dissimilarity-based-methods/cluster-analysis/hierarchical-cluster-analysis> (visited on 11/10/2021).
[3] What is Cluster Analysis? <URL: http://www.stat.columbia.edu/~madigan/W2025/notes/clustering.pdf>.
[4] What Is Cluster Analysis? When Should You Use It For Your Results? En. nov.. 10, 2021. <URL: https://www.qualtrics.com/experience-management/research/cluster-analysis/> (visited on 11/10/2021).
[5] P. Analytics. How to Perform Hierarchical Clustering using R R-bloggers. En-US. dic.. 2017. <URL: https://www.r-bloggers.com/2017/12/how-to-perform-hierarchical-clustering-using-r/> (visited on 11/23/2021).
[6] S. Bonnini and V. Mini. Cluster analysis: non hierarchical methods. Ferrara , 2019. <URL: http://www.unife.it/economia/lm.economics/lectures/statistics-for-economics-business/slides/lect-12_-non-hierarchical-ca>.
[7] S. Bonnini, V. Mini, and U. of Ferrara. Cluster Analysis: Non hierchical methods. 2019. <URL: http://www.unife.it/economia/lm.economics/lectures/statistics-for-economics-business /slides/lect-12_-non-hierarchical-ca>.
[8] G. Daróczi and R. Tsegelskyi. pander: An R ‘Pandoc’ Writer. R package version 0.6.4. 2021. <URL: https://CRAN.R-project.org/package=pander>.
[9] S. De la Fuente. Análisis de conglomerados - análisis de clúster. <URL: https://www.estadistica.net/Master-Econometria/Analisis_Cluster.pdf>.
[10] C. Hennig. fpc: Flexible Procedures for Clustering. R package version 2.2-9. 2020. <URL: https://CRAN.R-project.org/package=fpc>.
[11] A. Kassambara. ggpubr: ‘ggplot2’ Based Publication Ready Plots. R package version 0.4.0. 2020. <URL: https://CRAN.R-project.org/package=ggpubr>.
[12] A. Kassambara. Practical guide to cluster analysis in R: Unsupervised machine learning. STHDA, 2017.
[13] A. Kassambara and F. Mundt. factoextra: Extract and Visualize the Results of Multivariate Data Analyses. R package version 1.0.7. 2020. <URL: https://CRAN.R-project.org/package=factoextra>.
[14] M. Maechler, P. Rousseeuw, A. Struyf, et al. cluster: Cluster Analysis Basics and Extensions. R package version 2.1.2 - For new features, see the ‘Changelog’ file (in the package source). 2021. <URL: https://CRAN.R-project.org/package=cluster>.
[15] C. R. Patlolla. Understanding the concept of Hierarchical clustering Technique. En. may.. 2020. <URL: https://towardsdatascience.com/understanding-the-concept-of-hierarchical-clustering-technique-c6e8243758ec> (visited on 11/10/2021).
[16] R Core Team. R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing. Vienna, Austria, 2021. <URL: https://www.R-project.org/>.
[17] L. Scrucca, M. Fop, T. B. Murphy, et al. “mclust 5: clustering, classification and density estimation using Gaussian finite mixture models”. In: The R Journal 8.1 (2016), pp. 289-317. <URL: https://doi.org/10.32614/RJ-2016-021>.
[18] H. Wickham, R. François, L. Henry, et al. dplyr: A Grammar of Data Manipulation. R package version 1.0.6. 2021. <URL: https://CRAN.R-project.org/package=dplyr>.
[19] H. Zhu. kableExtra: Construct Complex Table with ‘kable’ and Pipe Syntax. R package version 1.3.4. 2021. <URL: https://CRAN.R-project.org/package=kableExtra>.