#1.- INTRODUCCIÓN
Una de las habilidades que marcan a las criaturas vivas es la capacidad de agrupar elementos similares en categorías que comparten ciertas propiedades. La clasificación hace parte esencial en varias disciplinas como el lenguaje, la biología, la química, la astronomía, etc. La clasificación se desarrolla principalmente como un método para organizar grandes cantidades de datos y describir patrones de similaridad y disimilaridad.
A continuación se presentan una serie de ejercicios que permitiran interiorizar el manejo de R y su aplicación en métodos de clasificación por clusters. El documento presenta una serie de ejercicios con datos generados y disponibles en el paquete Iris, para demostrar el uso principalmente de los métodos K-means y CLARA.
library(ggplot2)
library(car)
## Loading required package: carData
library(dplyr)
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
##
## recode
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(cluster)
library(simstudy)
library(data.table)
##
## Attaching package: 'data.table'
## The following objects are masked from 'package:dplyr':
##
## between, first, last
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ lubridate 1.9.3 ✔ tibble 3.2.1
## ✔ purrr 1.0.2 ✔ tidyr 1.3.0
## ✔ readr 2.1.4
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ data.table::between() masks dplyr::between()
## ✖ dplyr::filter() masks stats::filter()
## ✖ data.table::first() masks dplyr::first()
## ✖ lubridate::hour() masks data.table::hour()
## ✖ lubridate::isoweek() masks data.table::isoweek()
## ✖ dplyr::lag() masks stats::lag()
## ✖ data.table::last() masks dplyr::last()
## ✖ lubridate::mday() masks data.table::mday()
## ✖ lubridate::minute() masks data.table::minute()
## ✖ lubridate::month() masks data.table::month()
## ✖ lubridate::quarter() masks data.table::quarter()
## ✖ dplyr::recode() masks car::recode()
## ✖ lubridate::second() masks data.table::second()
## ✖ purrr::some() masks car::some()
## ✖ purrr::transpose() masks data.table::transpose()
## ✖ lubridate::wday() masks data.table::wday()
## ✖ lubridate::week() masks data.table::week()
## ✖ lubridate::yday() masks data.table::yday()
## ✖ lubridate::year() masks data.table::year()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(PerformanceAnalytics)
## Loading required package: xts
## Loading required package: zoo
##
## Attaching package: 'zoo'
##
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
##
##
## ######################### Warning from 'xts' package ##########################
## # #
## # The dplyr lag() function breaks how base R's lag() function is supposed to #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or #
## # source() into this session won't work correctly. #
## # #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
## # dplyr from breaking base R's lag() function. #
## # #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
## # #
## ###############################################################################
##
## Attaching package: 'xts'
##
## The following objects are masked from 'package:data.table':
##
## first, last
##
## The following objects are masked from 'package:dplyr':
##
## first, last
##
##
## Attaching package: 'PerformanceAnalytics'
##
## The following object is masked from 'package:graphics':
##
## legend
library(corrr)
#** 2.- DATOS**
x <- c(4, 4.5, 4, 7.5, 7, 6, 5, 5.5, 5, 6)
y <- c(4, 4.5, 4, 7.5, 7, 6, 5, 5.5, 5, 6) + 4
z <- c(5, 5.5, 4.8, 5.4, 4.7, 5.6, 5.3, 5.5, 5.2, 4.8)
datos <- data.frame(punto = rep(c("x", "y", "z"), each = 10),
respuesta = c(x,y,z),predictor = 1:10)
datos
## punto respuesta predictor
## 1 x 4.0 1
## 2 x 4.5 2
## 3 x 4.0 3
## 4 x 7.5 4
## 5 x 7.0 5
## 6 x 6.0 6
## 7 x 5.0 7
## 8 x 5.5 8
## 9 x 5.0 9
## 10 x 6.0 10
## 11 y 8.0 1
## 12 y 8.5 2
## 13 y 8.0 3
## 14 y 11.5 4
## 15 y 11.0 5
## 16 y 10.0 6
## 17 y 9.0 7
## 18 y 9.5 8
## 19 y 9.0 9
## 20 y 10.0 10
## 21 z 5.0 1
## 22 z 5.5 2
## 23 z 4.8 3
## 24 z 5.4 4
## 25 z 4.7 5
## 26 z 5.6 6
## 27 z 5.3 7
## 28 z 5.5 8
## 29 z 5.2 9
## 30 z 4.8 10
summary(datos)
## punto respuesta predictor
## Length:30 Min. : 4.000 Min. : 1.0
## Class :character 1st Qu.: 5.000 1st Qu.: 3.0
## Mode :character Median : 5.550 Median : 5.5
## Mean : 6.693 Mean : 5.5
## 3rd Qu.: 8.375 3rd Qu.: 8.0
## Max. :11.500 Max. :10.0
# Gráfico de datos
#----------------------------------------
ggplot(data=datos, aes(x= as.factor(predictor), y=respuesta, colour = punto)) +
geom_path(aes(group = punto)) +
geom_point() +
labs(x = "predictor") +
theme_bw() +
theme(legend.position = "bottom")
Una primera aproximación para determinar la similaridad entre
obervaciones es calculando la distancia total entre los puntos. Uno de
los métodos más empleados es la distancia euclidiana. Hay que tener en
cuenta, que entre más distantes sean dos puntos, más disimilares serán o
menos correlacionados serán.
x1 = matrix(c(x,y))
x2 = matrix(c(x,z))
x3 = matrix(c(y,z))
sum(dist(x1, method = "euclidean", diag = F, upper = F, p =2),1)
## [1] 528
sum(dist(x2, method = "euclidean", diag = F, upper = F, p =2),1)
## [1] 180.3
sum(dist(x3, method = "euclidean", diag = F, upper = F, p =2),1)
## [1] 509.3
R = matrix(c(x,y,z), ncol =3)
dcor = 1-cor(R)
dist(x = rbind(x,y,z), method = "euclidean")
## x y
## y 12.64911
## z 3.75100 13.98821
dcor <- 1 - cor(x=cbind(x,y,z), method = "pearson")
dcor
## x y z
## x 0.0000000 0.0000000 0.9466303
## y 0.0000000 0.0000000 0.9466303
## z 0.9466303 0.9466303 0.0000000
Ya que se esta utilizando una medida de 1 - Correlacién, se esta midiendo disimilaridad. Entre mas cercano el valor a 0 indica menor disimilaridad, mostrando que x y Y son los menos disimilares, y por ende podrian formar un grupo.
R = matrix(c(x,y,z),ncol=3)
dcor = cor(R)
dist(x = rbind(x,y,z), method = "euclidean")
## x y
## y 12.64911
## z 3.75100 13.98821
dcor <- cor(x=cbind(x,y,z), method = "pearson")
dcor
## x y z
## x 1.00000000 1.00000000 0.05336973
## y 1.00000000 1.00000000 0.05336973
## z 0.05336973 0.05336973 1.00000000
#3.- EDA
library(dplyr)
df <- data.frame(iris)
iris.2 <- iris[,-5]
species <- iris[,5]
#---------------------------------------
di=data.frame(df) %>%
mutate(Species=dplyr::recode(Species,
setosa="st",
versicolor="vs",
virginica="vg"))
#----------------------------------------
pairs(di[,1:4], col = species,lower.panel = NULL)
par(xpd = TRUE)
legend(x = 0.05, y = 0.4, cex = 2,
legend=as.character(levels(species)),
fill = unique(species))
En los resultados del análisis exploratorio se evidencia que para varias combinaciones de variables pueden formarse grupos diferenciados, especialmente de la especie setosa. Sabiendo esto, se justifica intentar correr los métodos de clasificación de clusters.
#4.- MÉTODO DE K MEANS
Este algoritmo de clasificación no supervisada agrupa objetos en k grupos basándose en la mínima suma de distancias entre cada objeto y el centroide de su grupo o cluster.
set.seed(20)
k.means.fit <- kmeans(di[,1:4], 3, nstart = 10)
k.means.fit
## K-means clustering with 3 clusters of sizes 50, 62, 38
##
## Cluster means:
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.006000 3.428000 1.462000 0.246000
## 2 5.901613 2.748387 4.393548 1.433871
## 3 6.850000 3.073684 5.742105 2.071053
##
## Clustering vector:
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [75] 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 2 3 3 3 3 2 3 3 3 3
## [112] 3 3 2 2 3 3 3 3 2 3 2 3 2 3 3 2 2 3 3 3 3 3 2 3 3 3 3 2 3 3 3 2 3 3 3 2 3
## [149] 3 2
##
## Within cluster sum of squares by cluster:
## [1] 15.15100 39.82097 23.87947
## (between_SS / total_SS = 88.4 %)
##
## Available components:
##
## [1] "cluster" "centers" "totss" "withinss" "tot.withinss"
## [6] "betweenss" "size" "iter" "ifault"
k.means.fit$centers
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.006000 3.428000 1.462000 0.246000
## 2 5.901613 2.748387 4.393548 1.433871
## 3 6.850000 3.073684 5.742105 2.071053
grupos = k.means.fit$cluster
table(di$Species, grupos) # Matriz de confusión
## grupos
## 1 2 3
## st 50 0 0
## vs 0 48 2
## vg 0 14 36
dif = data.frame(di, grupos)
dif = data.frame(dif) %>%
mutate(grupos=dplyr::recode(grupos,
"3" = "st",
"2"="vs",
"1"="vg"))
table(dif$grupos,dif$Species)
##
## st vs vg
## st 0 2 36
## vg 50 0 0
## vs 0 48 14
Al observar la matriz de confusión, se observa que la especie setosa quedó totalmente clasificada en un grupo, 48 de los datos de versicolor fueron agrupados, mientras que dos datos quedaron dentro de otro grupo. Virginica es el que presenta datos más confusos, ya que 16 de los 50 datos se encuentran en otro grupo junto con versicolor.
#5.- Combinación de K-means y PCA
A pesar de que la agrupación de variables puede ayudar en el análisis de la totalidad de datos, el proceso se hace cada vez más demandante entre mayor sea el número de variables. Por esta razón el PCA se hace una herramienta importante para identificar las variables que mayor aportan a la variabilidad de datos y trabajar con estas únicamente.
d2 <- scale(di[,1:4])
rownames(d2) <- di$Species
fviz_nbclust(x = d2, FUNcluster = kmeans, method = "wss", k.max = 6,
diss = get_dist(d2, method = "euclidean"), nstart = 50)
Esta figura de nümeros óptimos de clusters indica que, con los datos
actuales, puede hacerse una clasificación de máximo 15 clusters, aunque
ya se ha evidenciado que tres clusters pueden ser suficientes.
x|set.seed(123)
## logical(0)
d2f=data.frame(d2)
km_clusters <- kmeans(x = d2f, centers =3, nstart = 50)
fviz_cluster(object = km_clusters, data = d2f, show.clust.cent = TRUE,
ellipse.type = "euclid", star.plot = TRUE, repel = TRUE,
pointsize = 0.5, outlier.color = "darkred") +
labs(title = "Resultados clustering k-means") +
theme_bw() + theme(legend.position = "bottom")
En esta imagen se combinan entonces el método K-Means con PCA. Los dos
componentes graficados representan 95% de la variabilidad de los datos,
por lo que es más que suficiente trabajar con estos dos elementos.
require(cluster)
pam.res <- pam(d2f, 3)
# Visualización
fviz_cluster(pam.res, geom = "point", ellipse.type = "norm",
show.clust.cent = TRUE, star.plot = TRUE) +
labs(title = "Resultados clustering K-means") + theme_bw()
Con esta imagen se evidencia que hay cierto grado de conflicto entre los
clusters 2 y 3, ya que tienen cierta área solapada entre ambos. Estas
representaciones mezclan cluster y PCA, pero no indican el grado de
representación de cada variable en cada uno de los componentes.
#6.- BIPLOT PCA Y K-MEANS
data(iris)
pca <- prcomp(iris[,-5], scale=TRUE)
df.pca <- pca$x
kc <- kmeans(df.pca[,1:3], 3)
fviz_pca_biplot(pca, label="var", habillage=as.factor(kc$cluster)) +
labs(color=NULL) + ggtitle("") +
theme(text = element_text(size = 15),
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
legend.key = element_rect(fill = "white"))
Gracias a esta gráfica, ahora se sabe que la longitud de pétalo es la
variable más reresentada por el primer componente, al igual que el ancho
de pétalo. En el caso del componente dos, la variable ancho de pétalo es
la que está más representada. No obstante, hay algunos datos que
presentan inconsistencia, especialmente en la zona de conflicto entre
los clusters. Vamos a probar un método más robusto que no se vea
afectado por valores extraños.
#7.- K-MEDOIDS CON PAM
fviz_nbclust(x = d2f[,1:4], FUNcluster = pam, method = "wss", k.max = 6,
diss = dist(d2, method = "manhattan"))
set.seed(123)
pam_clusters <- pam(x = d2f[,1:4], k =3, metric = "manhattan")
pam_clusters$medoids
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## st.7 -1.0184372 0.7861738 -1.2791040 -1.3110521
## vg.16 0.7930124 -0.1315388 0.9868021 0.7880307
## vs.44 -0.2938574 -0.8198233 0.2503826 0.1320673
fviz_cluster(object = pam_clusters, data = d2f[,1:4],
ellipse.type = "t",repel = TRUE) +
theme_bw() + labs(title = "Resultados clustering PAM") +
theme(legend.position = "bottom")
medoids <- prcomp(d2f[,1:4])$x
medoids <- medoids[rownames(pam_clusters$medoids), c("PC1", "PC2")]
medoids <- as.data.frame(medoids)
colnames(medoids) <- c("x", "y")
# Creación del gráfico
fviz_cluster(object = pam_clusters, data = d2f[,1:4], ellipse.type = "t",
repel = TRUE) + theme_bw() +
# Se resaltan las observaciones que actúan como medoids
geom_point(data = medoids, color = "firebrick", size = 2) +
labs(title = "Resultados clustering PAM") +
theme(legend.position = "none")
El punto rojo en cada cluster es su medioide, a partir del cual se hace la clasificación.
#** 8.- MÉTODO JERÁRQUICO CLARA**
Cuando los datos a clasificar son demasiados, el algoritmo K-means o K-medoids exige una alta capacidad computacional para poder desarrollarlo. El método CLARA (Clustering Large Applications) combina la idea de K-medoides con el remuestreo y así poder trabajar con grandes volúmenes de datos de manera más eficiente.
Para ver las aplicaciones de este método se usarán nuevos datos relacionados con el color del café registrados en cinco medidas y dos fechas de maduración. El algoritmo que se utilizará es PAM.
set.seed(555)
dt1 <- genCorData(200, mu = c(37.88, 16.79, 11.74, 21.4, 34.04),
sigma = 1, rho = 0.5, corstr = "cs")
dt2 <- genCorData(200, mu = c(35.94, 17.90, 11.81, 21.77, 32.86),
sigma = 1, rho = 0.7, corstr = "cs")
dac <- rbind(dt1, dt2)
DDA = gl(2, 200, 400, labels = c("DDA224", "DDA231"))
dfc = data.frame(DDA,dac)
colnames(dfc) <- c("DDA", "id", "L", "a", "b", "c", "h")
dfc=dfc[,-2]
head(dfc)
## DDA L a b c h
## 1 DDA224 36.71324 16.59757 11.88936 20.80325 34.02769
## 2 DDA224 38.31073 15.76697 13.00676 21.46628 35.65491
## 3 DDA224 38.66201 17.00284 12.14174 22.81913 34.63488
## 4 DDA224 37.53979 17.02302 14.26060 21.62405 34.72869
## 5 DDA224 38.97227 15.98841 12.11759 20.35450 34.15341
## 6 DDA224 38.61491 17.14862 11.28327 22.67647 34.46416
options(digits = 2)
dfc %>%
split(.$DDA) %>%
map(select, -c(DDA)) %>%
map(cor)
## $DDA224
## L a b c h
## L 1.00 0.47 0.42 0.54 0.42
## a 0.47 1.00 0.46 0.51 0.45
## b 0.42 0.46 1.00 0.39 0.44
## c 0.54 0.51 0.39 1.00 0.53
## h 0.42 0.45 0.44 0.53 1.00
##
## $DDA231
## L a b c h
## L 1.00 0.66 0.68 0.70 0.68
## a 0.66 1.00 0.71 0.68 0.73
## b 0.68 0.71 1.00 0.69 0.70
## c 0.70 0.68 0.69 1.00 0.71
## h 0.68 0.73 0.70 0.71 1.00
clara_clusters <- clara(x = dfc, k=2, metric = "manhattan", stand = TRUE,
samples = 60, pamLike = TRUE)
clara_clusters$sample
## [1] 2 9 16 25 26 33 37 41 61 87 90 94 95 107 110 115 116 141 142
## [20] 146 148 150 159 161 183 193 204 222 223 228 244 249 251 253 256 257 282 284
## [39] 296 302 304 314 325 380
clara_clusters$medoids
## DDA L a b c h
## [1,] 1 37 17 12 21 34
## [2,] 2 36 18 12 22 33
clara_clusters$i.med
## [1] 94 302
clara_clusters$clustering
## [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [75] 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 1 1 1
## [112] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [149] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## [186] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [223] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [260] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [297] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [334] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
## [371] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
fviz_cluster(object = clara_clusters, ellipse.type = "t", geom = "point",
pointsize = 1.5) + theme_bw() +
labs(title = "Resultados clustering CLARA") +
theme(legend.position = "bottom")
medoides <- prcomp(dfc[,-1])$x
medoides <- medoides[rownames(pam_clusters$medoides), c("PC1", "PC2")]
medoides <- as.data.frame(medoides)
colnames(medoides) <- c("x", "y")
# Creación del gráfico
fviz_cluster(object = clara_clusters, data = d2f[,-1], ellipse.type = "t",
repel = TRUE,pointsize = 0.5) + theme_bw() +
# Se resaltan las observaciones que actúan como medoids
geom_point(data = medoides, color = "black", size = 2,) +
labs(title = "Resultados clustering PAM") +
theme(legend.position = "none")
# PCA
pca <- prcomp(dfc[,-1], scale=TRUE)
df.pca <- pca$x
# Cluster over the three first PCA dimensions
CLA <- clara(df.pca[,1:3], k = 2, metric = "manhattan", stand = TRUE,
samples = 60, pamLike = TRUE)
fviz_pca_biplot(pca, label="var", habillage=as.factor(CLA$cluster)) +
labs(color=NULL) + ggtitle("") +
theme(text = element_text(size = 15),
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
legend.key = element_rect(fill = "white"))
#9.- MÉTODO DE CLÁSIFICACIÓN JERÁRQUICOS
datj <- scale(dfc[,-1])
rownames(datj) <- dfc[,1]
# Matriz de distancias euclideas
mat_dist <- dist(x = datj, method = "euclidean")
# Dendrogramas con linkage complete y average
hc_euclidea_complete <- hclust(d = mat_dist, method = "complete")
hc_euclidea_average <- hclust(d = mat_dist, method = "average")
hc_euclidea_single <- hclust(d = mat_dist, method = "single")
hc_euclidea_ward.D2 <- hclust(d = mat_dist, method = "ward.D2")
hc_euclidea_median <- hclust(d = mat_dist, method = "median")
hc_euclidea_centroid <- hclust(d = mat_dist, method = "centroid")
hc_euclidea_mcquitty <- hclust(d = mat_dist, method = "mcquitty")
cor(x = mat_dist, cophenetic(hc_euclidea_complete))
## [1] 0.49
cor(x = mat_dist, cophenetic(hc_euclidea_average))
## [1] 0.62
cor(x = mat_dist, cophenetic(hc_euclidea_single))
## [1] 0.43
cor(x = mat_dist, cophenetic(hc_euclidea_ward.D2))
## [1] 0.5
cor(x = mat_dist, cophenetic(hc_euclidea_median))
## [1] 0.38
cor(x = mat_dist, cophenetic(hc_euclidea_centroid))
## [1] 0.54
cor(x = mat_dist, cophenetic(hc_euclidea_mcquitty))
## [1] 0.48
set.seed(101)
hc_euclidea_av <- hclust(d = dist(datj, method = "euclidean"),
method = "centroid")
fviz_dend(x = hc_euclidea_av, k = 2, cex = 0.5,
k_colors = c("purple","lightgrey"),color_labels_by_k = T,
lwd = 0.2,type = "c",label_cols = rainbow(400),
rect_lty = "blue") +
geom_hline(yintercept = 3.65, linetype = "dashed") +
labs(title = "Herarchical clustering",
subtitle = "Distancia euclídea, Centroide, k=2")
## Warning in get_col(col, k): Length of color vector was shorter than the number
## of clusters - color vector was recycled
## 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.
## Warning: Removed 1 rows containing missing values (`geom_hline()`).
set.seed(101)
hc_euclidea_av <- hclust(d = dist(x = datj, method = "euclidean"),
method = "centroid")
fviz_dend(x = hc_euclidea_av, k = 2, cex = 0.5,
k_colors = c("purple","lightgrey"),color_labels_by_k = T,
lwd = 0.2,type = "r",label_cols = rainbow(400),
rect_lty = "blue") +
geom_hline(yintercept = 3.65, linetype = "dashed") +
labs(title = "Herarchical clustering",
subtitle = "Distancia euclídea, Centroide, k=2")
## Warning in get_col(col, k): Length of color vector was shorter than the number
## of clusters - color vector was recycled
hc_euclidea_av <- hclust(d = dist(x = datj, method = "euclidean"),
method = "average")
fviz_dend(x = hc_euclidea_av, k = 2, cex = 0.5,
k_colors = c("purple","lightgrey"),color_labels_by_k = T,
lwd = 0.2,type = "c",label_cols = rainbow(400),
rect_lty = "blue") +
geom_hline(yintercept = 3.65, linetype = "dashed") +
labs(title = "Herarchical clustering",
subtitle = "Distancia euclídea, Average, k=2")
hc_euclidea_av <- hclust(d = dist(x = datj, method = "euclidean"),
method = "average")
fviz_dend(x = hc_euclidea_av, k = 2, cex = 0.5,
k_colors = c("purple","lightgrey"),color_labels_by_k = T,
lwd = 0.2,type = "r",label_cols = rainbow(400),
rect_lty = "blue") +
geom_hline(yintercept = 3.65, linetype = "dashed") +
labs(title = "Herarchical clustering",
subtitle = "Distancia euclidea, Average, k=2")
hc_euclidea_av <- hclust(d = dist(x = datj, method = "euclidean"),
method = "average")
fviz_dend(x = hc_euclidea_av, k = 5, cex = 0.5,
k_colors = c("lightblue","blue", "red", "darkred", "purple"),color_labels_by_k = T,
lwd = 0.2,type = "r",label_cols = rainbow(400),
rect_lty = "darkgreen") +
geom_hline(yintercept = 3, linetype = "dashed") +
labs(title = "Herarchical clustering",
subtitle = "Distancia euclidea, Average, k=5")