Cluster jerárquico en R
Importar datos:
datos <- read.csv("EAM_2019-v2.csv", sep = ";", dec = ",", header = T)
print(head(datos))
  ï..gasto_personal inversion_AF    ventas
1          32334949     92544622 321070109
2           5669798     69317638  86597330
3          11081213     50853587  26727389
4          47892609     42426113 388005721
5          56410101     35164028 390070138
6          20536798     27028346 490639882
colnames(datos) <- c("Gasto_personal", "Inversión_AF", "Ventas")
str(datos)
'data.frame':       216 obs. of  3 variables:
 $ Gasto_personal: int  32334949 5669798 11081213 47892609 56410101 20536798 14001910 38533922 21397321 3478034 ...
 $ Inversión_AF  : int  92544622 69317638 50853587 42426113 35164028 27028346 25150313 23019658 22007282 21924323 ...
 $ Ventas        : int  321070109 86597330 26727389 388005721 390070138 490639882 379365700 488079500 233432780 9932602 ...
dim(datos)
- 216
 - 3
 
df <- datos[, c("Gasto_personal", "Ventas")]
library(ggplot2)
ggplot(data = df, aes(x = Gasto_personal, y = Ventas))+
    geom_point()
Escalamiento de variables:
df_scaled <- scale(df)
Distancias:
dist <- dist(df_scaled, method = "euclidean")
Matriz de distancias:
print(as.matrix(dist)[1:6, 1:6])
         1         2         3         4         5        6
1 0.000000 2.9088632 3.0901009 1.3159100 1.9144336 1.763064
2 2.908863 0.0000000 0.6745543 4.1740457 4.6909913 3.798116
3 3.090101 0.6745543 0.0000000 4.2665706 4.7206485 4.227799
4 1.315910 4.1740457 4.2665706 0.0000000 0.6410866 2.255214
5 1.914434 4.6909913 4.7206485 0.6410866 0.0000000 2.846148
6 1.763064 3.7981163 4.2277993 2.2552142 2.8461482 0.000000
Cluster jerárquico:
Usaremos la función hclust() de la librería stat.
En esta función se debe pasar el vector con las distancias calculadas
con la función dist().
Para realizar el agrupamiento la función hclust() tiene varios
métodos: "ward.D" , "ward.D2", "single", "complete",
"average", "mcquitty", "median" o "centroid".
"ward.D"y"ward.D2": minimiza la varianza total dentro del cluster. En cada paso, une el par de cluster con una distancia mínima entre clusters."ward.D2"eleva al cuadrado las distancias calculadas condist()."single": a diferencia del anterior, lo hace con el valor mínimo. Tiende a producir grupos largo. Es el método de la distancia mínima."complete": la distancia entre dos grupos se define como el valor máximo de todas las distancias por pares entre los elementos del grupo 1 y los elementos del grupo 2. Tiene a producir cluster más compactos. Es el método de la distancia máxima."average": la distancia entre dos clusters se define como la distancia promedio entre los elementos del cluster 1 y los elementos del cluster 2. Es el método del promedio."mcquitty": promedio ponderado."median": mediana."centroid": usa las distancias entre el centroide 1 y el centroide 2.
hc <- hclust(d = dist, method = "ward.D2")
print(hc)
Call:
hclust(d = dist, method = "ward.D2")
Cluster method   : ward.D2
Distance         : euclidean
Number of objects: 216
Dendograma:
Visualizaremos el dendograma con la función fviz_dend() de la
librería factoextra.
Los principales argumentos de esta función son:
x: el objeto creado conhclust().k: cantidad de clusters. Primero no especificaremos este valor.h: para cortar el dendograma por altura. Primero no especificaremos este valor.
library("factoextra")
Warning message:
"package 'factoextra' was built under R version 4.1.3"
Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
fviz_dend(hc)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Distancia cofenética (cophenetic distances):
Para comprobar si las distancias del árbol reflejan las distancias
originales. Se calcula la correlación entre las distancias cofenéticas y
los datos de las distancias originales generadas por la función
dist().
Cuanto más cerca esté el valor del coeficiente de correlación a 1, con mayor precisión la solución de agrupación reflejará sus datos.
La distancia cofenética del árbol se calcula con la función
cophenetic().
coph <- cophenetic(hc)
cor(dist, coph)
Corte del dendograma:
El árbol se puede cortar a una altura determinada o por cantidad de clusters.
La función de la base de R, cutree() permite cortar el árbol
generado por hclust()por cantidad de clusters, k, o por
altura, h. Devuelve un vector que contiene el número de cluster de
cada observación.
\(k = 3\)
grp <- cutree(hc, k = 3)
print(head(grp))           # vector con los números del cluster de cada observación.
[1] 1 2 2 1 1 1
Cantidad de observaciones en cada cluster:
table(grp)
grp
  1   2   3
 17 135  64
Visualizar el dendograma cortado:
fviz_dend(hc, k = 3,                        # Cortar el árbol en k clusters.
            color_labels_by_k = TRUE,       # Color por clusters.
            rect = TRUE)                    # Agragar un rectángulo a cada cluster.
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Visualizar los clusters en el gráfico de dispersión:
fviz_cluster(list(data = df, cluster = grp),
            ellipse.type = "convex",                                # Forma del cluster.
            repel = TRUE,                                           # Para evitar solapar las etiquetas
            show.clust.cent = TRUE,                                 # Centroides.
            ggtheme = theme_minimal())
Warning message:
"ggrepel: 148 unlabeled data points (too many overlaps). Consider increasing max.overlaps"
Otra forma:
Tenemos dos funciones del paquete cluster que calculan el
agrupamiento aglomerativo y divisivo.
agnes(): aglomerativo.diana(): Divisivo.
Con estas funciones no se necesitan ejecutar scale(), dist() y
hclust() por separado.
library("cluster")
Warning message:
"package 'cluster' was built under R version 4.1.3"
agnes <- agnes(x = df,                       # Conjunto de datos original.
               stand = TRUE,                  # Escalamiento de las variables.
                    metric = "euclidean",     # Métodos para las distancias.
                    method = "ward")         # Método para el agrupamiento.
diana <- diana(x = df,
               stand = TRUE,
               metric = "euclidean")
fviz_dend(agnes, k = 3)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
fviz_dend(diana, k = 3)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Visualización del dendograma
install.packages("dendextend")
Gráfico inicial:
fviz_dend(hc,)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Títulos y etiquetas:
fviz_dend(hc, cex = 0.5,
            main = "Dendrogram - ward.D2",
            xlab = "Objects", ylab = "Distance", sub = "")
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Horizontal:
fviz_dend(hc, cex = 0.5, horiz = TRUE)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Cluster sombreados:
fviz_dend(hc, k = 3,
            cex = 0.5,
            k_colors = c("#2E9FDF", "#00AFBB"),
            color_labels_by_k = TRUE,
            rect = TRUE,
            rect_border = c("#2E9FDF", "#00AFBB"),
            rect_fill = TRUE)
Warning message in get_col(col, k): "Length of color vector was shorter than the number of clusters - color vector was recycled" Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead." Warning message in if (color == "cluster") color <- "default": "la condición tiene longitud > 1 y sólo el primer elemento será usado"
Otro tema:
fviz_dend(hc, k = 3,
            cex = 0.5,
            k_colors = c("#2E9FDF", "#00AFBB"),
            color_labels_by_k = TRUE,
            ggtheme = theme_gray())
Warning message in get_col(col, k): "Length of color vector was shorter than the number of clusters - color vector was recycled" Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Paleta ``jco``:
fviz_dend(hc, cex = 0.5, k = 3,
            k_colors = "jco")
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Horizontal y paleta ``jco``:
fviz_dend(hc, k = 3, cex = 0.4, horiz = TRUE, k_colors = "jco",
            rect = TRUE, rect_border = "jco", rect_fill = TRUE)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Circular:
fviz_dend(hc, cex = 0.5, k = 3,
            k_colors = "jco", type = "circular")
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Ejemplo base de datos con etiquetas:
datos2 <- read.csv("Estado de resultados-2020.csv", sep = ";", dec = ",", header = T)
str(datos2)
'data.frame':       2431 obs. of  25 variables:
 $ Clasificación.Industrial.Internacional.Uniforme.Versión.4.A.C..CIIU.                                                                                                                                                                                                           : chr  "H4930 - Transporte por tuberías" "H4930 - Transporte por tuberías" "H4930 - Transporte por tuberías" "B0510 - Extracción de hulla (carbón de piedra)" ...
 $ Departamento.de.la.dirección.del.domicilio                                                                                                                                                                                                                                     : chr  "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
 $ Ciudad.de.la.dirección.del.domicilio                                                                                                                                                                                                                                           : chr  "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." "BOGOTA D.C." ...
 $ Ingresos.de.actividades.ordinarias                                                                                                                                                                                                                                             : num  1.28e+09 3.45e+08 1.27e+09 5.47e+08 1.05e+07 ...
 $ Costo.de.ventas                                                                                                                                                                                                                                                                : num  2.11e+08 6.90e+07 2.10e+08 6.68e+08 2.82e+06 ...
 $ Ganancia.bruta                                                                                                                                                                                                                                                                 : int  1068652505 276350200 1059846508 -120135345 7678364 998518794 2434907 71030143 345277614 11502748 ...
 $ Otros.ingresos                                                                                                                                                                                                                                                                 : int  518601 1297021 521537 NA 204440 5269820 120010 696112 1200917 886120 ...
 $ Gastos.de.ventas                                                                                                                                                                                                                                                               : int  10888517 NA 10995074 40370796 NA 11927981 NA NA 162037834 4072887 ...
 $ Gastos.de.administración                                                                                                                                                                                                                                                       : int  19462303 5326805 19714849 6433695 1172780 18607768 2041618 39451679 93520107 2122394 ...
 $ Otros.gastos                                                                                                                                                                                                                                                                   : int  NA 7316716 NA NA 2718133 NA 143129 34551428 8240400 636098 ...
 $ Otras.ganancias..pérdidas.                                                                                                                                                                                                                                                     : int  NA NA NA 127926859 0 NA NA NA NA NA ...
 $ Ganancia..pérdida..por.actividades.de.operación                                                                                                                                                                                                                                : int  1038820286 265003700 1029658122 -39012977 3991891 973252865 370170 -2276852 82680190 5557489 ...
 $ Diferencia.entre.el.importe.en.libros.de.dividendos.pagaderos.e.importe.en.libros.de.activos.distribuidos.distintos.al.efectivo                                                                                                                                                : int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ganancias..pérdidas..que.surgen.de.la.baja.en.cuentas.de.activos.financieros.medidos.al.costo.amortizado                                                                                                                                                                       : int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ingresos.financieros                                                                                                                                                                                                                                                           : int  93766912 9573579 NA 3221283 5110192 NA 91804 NA 898026 129379 ...
 $ Costos.financieros                                                                                                                                                                                                                                                             : int  NA NA 173721640 18086470 5026816 72100638 281008 3185442 383162 4138026 ...
 $ Deterioro.de.valor.de.ganancias.y.reversión.de.pérdidas.por.deterioro.de.valor..pérdidas.por.deterioro.de.valor..determinado.de.acuerdo.con.la.NIIF.9                                                                                                                          : int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ganancias..pérdidas..que.surgen.de.diferencias.entre.el.costo.amortizado.anterior.y.el.valor.razonable.de.activos.financieros.reclasificados.de.la.categoría.de.medición.costo.amortizado.a.la.categoría.de.medición.de.valor.razonable.con.cambios.en.resultados              : int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ganancia..pérdida..acumulada.anteriormente.reconocida.en.otro.resultado.integral.que.surge.de.la.reclasificación.de.activos.financieros.de.la.categoría.de.medición.de.valor.razonable.con.cambios.en.otro.resultado.integral.a.la.de.valor.razonable.con.cambios.en.resultados: int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ganancias..pérdidas..de.cobertura.por.cobertura.de.un.grupo.de.partidas.con.posiciones.de.riesgo.compensadoras                                                                                                                                                                 : int  NA NA NA NA NA NA NA NA NA 0 ...
 $ Ganancia..pérdida...antes.de.impuestos                                                                                                                                                                                                                                         : int  1132587198 274577279 855936482 -53878164 4075267 901152227 180966 -5462294 83195054 1548842 ...
 $ Ingreso..gasto..por.impuestos                                                                                                                                                                                                                                                  : int  253919393 87737163 328295928 30576990 1436579 276491490 -26116 9156763 29562532 364786 ...
 $ Ganancia..pérdida..procedente.de.operaciones.continuadas                                                                                                                                                                                                                       : int  878667805 186840116 527640554 -84455154 2638688 624660737 207082 -14619057 53632522 1184056 ...
 $ Ganancia..pérdida..procedente.de.operaciones.discontinuadas                                                                                                                                                                                                                    : int  NA NA NA NA NA NA NA NA NA NA ...
 $ Ganancia..pérdida.                                                                                                                                                                                                                                                             : int  878667805 186840116 527640554 -84455154 2638688 624660737 207082 -14619057 53632522 1184056 ...
NA = 0:
datos2[is.na(datos2)] <- 0
Agrupar los datos por código ciuu y sumar:
library(tidyverse)
Warning message:
"package 'tidyverse' was built under R version 4.1.3"
-- [1mAttaching packages[22m --------------------------------------- tidyverse 1.3.1 --
[32mv[39m [34mtibble [39m 3.1.6     [32mv[39m [34mdplyr  [39m 1.0.8
[32mv[39m [34mtidyr  [39m 1.2.0     [32mv[39m [34mstringr[39m 1.4.0
[32mv[39m [34mreadr  [39m 2.1.2     [32mv[39m [34mforcats[39m 0.5.1
[32mv[39m [34mpurrr  [39m 0.3.4
Warning message:
"package 'readr' was built under R version 4.1.3"
-- [1mConflicts[22m ------------------------------------------ tidyverse_conflicts() --
[31mx[39m [34mdplyr[39m::[32mfilter()[39m masks [34mstats[39m::filter()
[31mx[39m [34mdplyr[39m::[32mlag()[39m    masks [34mstats[39m::lag()
df2 <- datos2 %>%
        group_by(Clasificación.Industrial.Internacional.Uniforme.Versión.4.A.C..CIIU.) %>%
        summarise(Ingresos.de.actividades.ordinarias = sum(Ingresos.de.actividades.ordinarias),
                 Ganancia..pérdida. = sum(Ganancia..pérdida.))
print(head(df2))
[90m# A tibble: 6 x 3[39m
  Clasificación.Industrial.Internacional.Unif~ Ingresos.de.act~ Ganancia..pérdi~
  [3m[90m<chr>[39m[23m                                                   [3m[90m<dbl>[39m[23m            [3m[90m<dbl>[39m[23m
[90m1[39m A0112 - Cultivo de arroz                             48[4m6[24m[4m4[24m[4m8[24m526          1[4m2[24m[4m9[24m[4m5[24m439
[90m2[39m A0113 - Cultivo de hortalizas, raíces y tub~         61[4m3[24m[4m7[24m[4m2[24m344          4[4m8[24m[4m2[24m[4m0[24m954
[90m3[39m A0121 - Cultivo de frutas tropicales y subt~         14[4m2[24m[4m2[24m[4m3[24m971         -[31m5[4m4[24m[4m2[24m[39m[31m[4m9[24m345[39m
[90m4[39m A0122 - Cultivo de plátano y banano                [4m1[24m135[4m6[24m[4m7[24m[4m7[24m192         52[4m5[24m[4m4[24m[4m7[24m865
[90m5[39m A0123 - Cultivo de café                               3[4m6[24m[4m2[24m[4m0[24m827          -[31m[4m3[24m[4m4[24m[4m3[24m[39m[31m548[39m
[90m6[39m A0124 - Cultivo de caña de azúcar                    53[4m1[24m[4m2[24m[4m1[24m589          5[4m7[24m[4m1[24m[4m8[24m585
Eliminar los código ciuu y dejar solo los nombres de las actividades económicas:
df2$ciiu <- str_split_fixed(df2$Clasificación.Industrial.Internacional.Uniforme.Versión.4.A.C..CIIU., "-", 2)[,2]
df2$Clasificación.Industrial.Internacional.Uniforme.Versión.4.A.C..CIIU. <- NULL
print(head(df2))
[90m# A tibble: 6 x 3[39m
  Ingresos.de.actividades.ordinarias Ganancia..pérdida. ciiu
                               [3m[90m<dbl>[39m[23m              [3m[90m<dbl>[39m[23m [3m[90m<chr>[39m[23m
[90m1[39m                           48[4m6[24m[4m4[24m[4m8[24m526            1[4m2[24m[4m9[24m[4m5[24m439 [90m"[39m Cultivo de arroz[90m"[39m
[90m2[39m                           61[4m3[24m[4m7[24m[4m2[24m344            4[4m8[24m[4m2[24m[4m0[24m954 [90m"[39m Cultivo de hortalizas~
[90m3[39m                           14[4m2[24m[4m2[24m[4m3[24m971           -[31m5[4m4[24m[4m2[24m[39m[31m[4m9[24m345[39m [90m"[39m Cultivo de frutas tro~
[90m4[39m                         [4m1[24m135[4m6[24m[4m7[24m[4m7[24m192           52[4m5[24m[4m4[24m[4m7[24m865 [90m"[39m Cultivo de plátano y ~
[90m5[39m                            3[4m6[24m[4m2[24m[4m0[24m827            -[31m[4m3[24m[4m4[24m[4m3[24m[39m[31m548[39m [90m"[39m Cultivo de café[90m"[39m
[90m6[39m                           53[4m1[24m[4m2[24m[4m1[24m589            5[4m7[24m[4m1[24m[4m8[24m585 [90m"[39m Cultivo de caña de az~
Asignar el index (los nombres de las filas):
df2 <- as.data.frame(df2)
rownames(df2) <- df2$ciiu
df2$ciiu <- NULL
print(head(df2))
                                             Ingresos.de.actividades.ordinarias
Cultivo de arroz                                                       48648526
Cultivo de hortalizas, raíces y tubérculos                             61372344
Cultivo de frutas tropicales y subtropicales                           14223971
Cultivo de plátano y banano                                          1135677192
Cultivo de café                                                         3620827
Cultivo de caña de azúcar                                              53121589
                                             Ganancia..pérdida.
Cultivo de arroz                                        1295439
Cultivo de hortalizas, raíces y tubérculos              4820954
Cultivo de frutas tropicales y subtropicales           -5429345
Cultivo de plátano y banano                            52547865
Cultivo de café                                         -343548
Cultivo de caña de azúcar                               5718585
Cambiar el nombre de las columnas (variables):
colnames(df2) <- c("Ingresos", "Utilidad_Neta")
df2 <- df2[1:20,]
print(head(df2))
                                               Ingresos Utilidad_Neta
Cultivo de arroz                               48648526       1295439
Cultivo de hortalizas, raíces y tubérculos     61372344       4820954
Cultivo de frutas tropicales y subtropicales   14223971      -5429345
Cultivo de plátano y banano                  1135677192      52547865
Cultivo de café                                 3620827       -343548
Cultivo de caña de azúcar                      53121589       5718585
ggplot(data = df2, aes(x = Ingresos, y = Utilidad_Neta))+
    geom_point()
Escalamiento de variables:
df2_scaled <- scale(df2)
Distancias:
dist2 <- dist(df2_scaled, method = "euclidean")
Matriz de distancias:
print(as.matrix(dist2)[1:6, 1:6])
                                              Cultivo de arroz
Cultivo de arroz                                     0.0000000
Cultivo de hortalizas, raíces y tubérculos           0.1532693
Cultivo de frutas tropicales y subtropicales         0.2954620
Cultivo de plátano y banano                          2.9120916
Cultivo de café                                      0.1057447
Cultivo de caña de azúcar                            0.1904133
                                              Cultivo de hortalizas, raíces y tubérculos
Cultivo de arroz                                                              0.15326934
Cultivo de hortalizas, raíces y tubérculos                                    0.00000000
Cultivo de frutas tropicales y subtropicales                                  0.44855235
Cultivo de plátano y banano                                                   2.78395735
Cultivo de café                                                               0.24405950
Cultivo de caña de azúcar                                                     0.04122236
                                              Cultivo de frutas tropicales y subtropicales
Cultivo de arroz                                                                 0.2954620
Cultivo de hortalizas, raíces y tubérculos                                       0.4485524
Cultivo de frutas tropicales y subtropicales                                     0.0000000
Cultivo de plátano y banano                                                      3.1736733
Cultivo de café                                                                  0.2195407
Cultivo de caña de azúcar                                                        0.4843143
                                              Cultivo de plátano y banano
Cultivo de arroz                                                 2.912092
Cultivo de hortalizas, raíces y tubérculos                       2.783957
Cultivo de frutas tropicales y subtropicales                     3.173673
Cultivo de plátano y banano                                      0.000000
Cultivo de café                                                  3.016988
Cultivo de caña de azúcar                                        2.765486
                                              Cultivo de café
Cultivo de arroz                                    0.1057447
Cultivo de hortalizas, raíces y tubérculos          0.2440595
Cultivo de frutas tropicales y subtropicales        0.2195407
Cultivo de plátano y banano                         3.0169883
Cultivo de café                                     0.0000000
Cultivo de caña de azúcar                           0.2747690
                                              Cultivo de caña de azúcar
Cultivo de arroz                                             0.19041328
Cultivo de hortalizas, raíces y tubérculos                   0.04122236
Cultivo de frutas tropicales y subtropicales                 0.48431431
Cultivo de plátano y banano                                  2.76548585
Cultivo de café                                              0.27476897
Cultivo de caña de azúcar                                    0.00000000
Cluster jerárquico:
hc2 <- hclust(d = dist2, method = "ward.D2")
print(hc2)
Call:
hclust(d = dist2, method = "ward.D2")
Cluster method   : ward.D2
Distance         : euclidean
Number of objects: 20
Dendograma:
fviz_dend(hc2)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Distancia cofenética (cophenetic distances):
coph2 <- cophenetic(hc2)
cor(dist2, coph2)
Corte del dendograma:
\(k = 2\)
grp2 <- cutree(hc2, k = 2)
print(head(grp2))           # vector con los números del cluster de cada observación.
                            Cultivo de arroz
                                           1
  Cultivo de hortalizas, raíces y tubérculos
                                           1
Cultivo de frutas tropicales y subtropicales
                                           1
                 Cultivo de plátano y banano
                                           2
                             Cultivo de café
                                           1
                   Cultivo de caña de azúcar
                                           1
Cantidad de observaciones en cada cluster:
table(grp2)
grp2
 1  2
16  4
Visualizar el dendograma:
fviz_dend(hc2, k = 2, horiz = TRUE)
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
fviz_dend(hc2, cex = 0.5, k = 2, type = "circular")
Warning message: "guides(<scale> = FALSE) is deprecated. Please use guides(<scale> = "none") instead."
Visualizar los clusters en el gráfico de dispersión:
fviz_cluster(list(data = df2, cluster = grp2),
            ellipse.type = "convex",                                # Forma del cluster.
            repel = TRUE,                                           # Para evitar solapar las etiquetas
            show.clust.cent = TRUE,                                 # Centroides.
            ggtheme = theme_minimal())
Warning message:
"ggrepel: 7 unlabeled data points (too many overlaps). Consider increasing max.overlaps"