Introduccion al análisis de clústeres K-means

El clustering nos permite identificar las observaciones que son similares, y potencialmente categorizarlas en ellas. El clustering de K-means es el método de clustering más sencillo y el más utilizado para dividir un conjunto de datos en un conjunto de k grupos o k centroides

Para replicar el análisis de esta sección necesitará cargar los siguientes paquetes, estos se utilizaran durante todo el informe:

library(tidyverse)  # data manipulation
## Warning: package 'tidyverse' was built under R version 4.1.3
## -- Attaching packages --------------------------------------- tidyverse 1.3.2 --
## v ggplot2 3.4.0      v purrr   0.3.5 
## v tibble  3.1.8      v dplyr   1.0.10
## v tidyr   1.2.1      v stringr 1.4.1 
## v readr   2.1.3      v forcats 0.5.2
## Warning: package 'ggplot2' was built under R version 4.1.3
## Warning: package 'tibble' was built under R version 4.1.3
## Warning: package 'tidyr' was built under R version 4.1.3
## Warning: package 'readr' was built under R version 4.1.3
## Warning: package 'purrr' was built under R version 4.1.3
## Warning: package 'dplyr' was built under R version 4.1.3
## Warning: package 'stringr' was built under R version 4.1.3
## Warning: package 'forcats' was built under R version 4.1.3
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(cluster)    # clustering algorithms
library(factoextra) # clustering algorithms & visualization
## Warning: 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

Preparación de datos

Para realizar un análisis de clusters en R, generalmente, los datos deben prepararse de la siguiente manera:

  1. Las filas son observaciones (individuos) y las columnas son variables
  2. Cualquier valor que falte en los datos debe eliminarse o estimarse.
  3. Los datos deben estar estandarizados (es decir, escalados) para que las variables sean comparables. Recordemos que la estandarización consiste en transformar las variables de tal manera que tengan media cero y desviación estándar uno.

En este apartado usaremos el conjunto de datos R integrado USArrests, que contiene estadísticas de arrestos por cada 100,000 residentes por asalto,asesinato y violación en cada uno de los 50 estados de EE. UU. En 1973. También incluye el porcentaje de la población que vive en zonas urbanas.

data("USArrests") # Loading the data set
df <- scale(USArrests) # Scaling the data
# View the firt 3 rows of the data
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

Para eliminar cualquier valor ausente que pueda estar presente en sus datos, escriba:

df <- na.omit(df)

Estimacion del numero optimo de clusters

La idea básica detrás de los métodos de partición de clústeres es definir clústeres de manera que la variación total dentro del clúster (conocida como variación total dentro del clúster o suma total del cuadrado dentro del clúster) se minimice:

\[ minimize ( \sum_{k=1}^{k}W(C_k))\]

La suma total del cuadrado dentro del conglomerado (wss) mide la compacidad del conglomerado y queremos que sea lo más pequeño posible. Por tanto, podemos utilizar el siguiente algoritmo para definir los clústeres óptimos:

  1. Calcule el algoritmo de agrupamiento (p. Ej., Agrupamiento de k-medias) para diferentes valores de k . Por ejemplo, variando k de 1 a 10 grupos.
  2. Para cada k , calcule la suma total del cuadrado dentro del conglomerado (wss)
  3. Trace la curva de wss según el número de clusters k .
  4. La ubicación de una curva (rodilla) en la parcela se considera generalmente como un indicador del número apropiado de grupos.

Podemos implementar esto en R con el siguiente código. Los resultados sugieren que 4 es el número óptimo de grupos, ya que parece ser la flexión de la rodilla (o codo).

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

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

Cálculo de la agrupación de k-means

Como el algoritmo de clustering de k-means comienza con k centros seleccionados aleatoriamente,siempre se recomienda utilizar la función set.seed() para establecer una semilla para el number generator. El objetivo es hacer reproducibles los resultados, para que el lector de este artículo obtenga exactamente los mismos resultados que se muestran a continuación: El código R que se muestra a continuación realiza la agrupación de k-means con k = 4:

# Compute k-means with k = 4
set.seed(123)
km.res <- kmeans(df, 4, nstart = 25)
# Print the results
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"

Es posible calcular la media de cada una de las variables por clusters utilizando los datos originales:

aggregate(USArrests, by=list(cluster=km.res$cluster), mean)
##   cluster   Murder   Assault UrbanPop     Rape
## 1       1 13.93750 243.62500 53.75000 21.41250
## 2       2  3.60000  78.53846 52.07692 12.17692
## 3       3  5.65625 138.87500 73.87500 18.78125
## 4       4 10.81538 257.38462 76.00000 33.19231

Si quieres añadir las clasificaciones de puntos a los datos originales, utiliza esto:

dd <- cbind(USArrests, cluster = km.res$cluster)
head(dd)
##            Murder Assault UrbanPop Rape cluster
## Alabama      13.2     236       58 21.2       1
## Alaska       10.0     263       48 44.5       4
## Arizona       8.1     294       80 31.0       4
## Arkansas      8.8     190       50 19.5       1
## California    9.0     276       91 40.6       4
## Colorado      7.9     204       78 38.7       4

Acceso a los resultados de la función kmeans()

# Número de cluster para cada una de las observaciones
km.res$cluster
##        Alabama         Alaska        Arizona       Arkansas     California 
##              1              4              4              1              4 
##       Colorado    Connecticut       Delaware        Florida        Georgia 
##              4              3              3              4              1 
##         Hawaii          Idaho       Illinois        Indiana           Iowa 
##              3              2              4              3              2 
##         Kansas       Kentucky      Louisiana          Maine       Maryland 
##              3              2              1              2              4 
##  Massachusetts       Michigan      Minnesota    Mississippi       Missouri 
##              3              4              2              1              4 
##        Montana       Nebraska         Nevada  New Hampshire     New Jersey 
##              2              2              4              2              3 
##     New Mexico       New York North Carolina   North Dakota           Ohio 
##              4              4              1              2              3 
##       Oklahoma         Oregon   Pennsylvania   Rhode Island South Carolina 
##              3              3              3              3              1 
##   South Dakota      Tennessee          Texas           Utah        Vermont 
##              2              1              4              3              2 
##       Virginia     Washington  West Virginia      Wisconsin        Wyoming 
##              3              3              2              2              3
head(km.res$cluster, 4)
##  Alabama   Alaska  Arizona Arkansas 
##        1        4        4        1
# Tamaño del grupo
km.res$size
## [1]  8 13 16 13
# Medios de agrupación
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

Visualización de los clusters de k-means

La función fviz_cluster() [paquete factoextra] puede utilizarse para visualizar fácilmente los clusters de k-means clusters. Toma los resultados de k-means y los datos originales como argumentos. En el gráfico resultante, las observaciones se representan mediante puntos, utilizando componentes principales si el número de variables es superior a 2. También es posible dibujar una elipse de concentración alrededor de cada clúster.

fviz_cluster(km.res, data = df,
palette = c("#2E9FDF", "#00AFBB", "#E7B800", "#FC4E07"),
ellipse.type = "euclid", # Concentration ellipse
star.plot = TRUE, # Add segments from centroids to items
repel = TRUE, # Avoid label overplotting (slow)
ggtheme = theme_minimal()
)

Resumen

La agrupación de K-means puede utilizarse para clasificar las observaciones en k grupos, basándose en su similitud. Cada grupo está representado por el valor medio de los puntos del grupo, conocido como centroide del clúster. El algoritmo de K-means requiere que los usuarios especifiquen el número de clústeres a generar. La función de R kmeans() [paquete stats] puede utilizarse para calcular el algoritmo k-means. El formato simplificado es kmeans(x, centers), donde “x” son los datos y centers es el número de clusters a producir. Después de calcular el clustering de k-means, la función de R fviz_cluster() [paquete factoextra] puede utilizarse para visualizar los resultados. El formato es fviz_cluster(km.res, data), donde km.res son los resultados de k-means y data corresponde a los conjuntos de datos originales.

K-Medoids

El algoritmo k-medoids es un enfoque de clustering relacionado con el clustering k-means para dividir un conjunto de datos en k grupos o clusters. En el clustering k-medoids cada clúster está representado por uno de los puntos de datos del clúster. Estos puntos se denominan medoides de clúster.

Concepto PAM

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

PAM en R

Data

Utilizaremos los conjuntos de datos de demostración “USArrests”, que empezamos escalando, utilizando la función R scale() como sigue:

data("USArrests") # Load the data set
df <- scale(USArrests) # Scale the data
head(df, n = 3) # View the firt 3 rows of the data
##             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

Se instalan las siguientes paqueterias :

install.packages(c("cluster", "factoextra"))
## Warning: packages 'cluster', 'factoextra' are in use and will not be installed
library(cluster)
library(factoextra)
Estimación del número óptimo de Clusters

Para estimar el número óptimo de clusters, utilizaremos el método de la silueta media.

Método de silueta promedio

El enfoque de silueta promedio mide la calidad de un agrupamiento.Es decir, determina la calidad de cada artículo de su grupo. El ancho promedio de la silueta indica una buena agrupación. El método de silueta promedio calcula la silueta promedio de observaciones para diferentes valores de k’ . El número óptimo de clusters ‘k’ es el que maximiza la silueta promedio en un rango de valores posibles para k.

Podemos usar la silhouette función en el paquete de clúster para calcular el ancho de silueta promedio.

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

Computacion PAM clustering

El código R siguiente calcula el algoritmo PAM con k = 2:

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"

Si quieres añadir las clasificaciones de puntos a los datos originales, utiliza esto:

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
Acceso a los resultados de la función PAM()

La función pam() devuelve un objeto de la clase pam que incluye componentes:

# Cluster medoids: New Mexico, Nebraska
pam.res$medoids
##                Murder    Assault   UrbanPop       Rape
## New Mexico  0.8292944  1.3708088  0.3081225  1.1603196
## Nebraska   -0.8008247 -0.8250772 -0.2445636 -0.5052109
# Cluster numbers
head(pam.res$clustering)
##    Alabama     Alaska    Arizona   Arkansas California   Colorado 
##          1          1          1          2          1          1
Visualización de PAM clusters

Para visualizar los resultados de la partición, utilizaremos la función fviz_cluster() [factoextrapaquete]. Dibuja un gráfico de dispersión de los puntos de datos coloreados por los números de cluster.

fviz_cluster(pam.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
repel = TRUE, # Avoid label overplotting (slow)
ggtheme = theme_classic()
)

Resumen

El algoritmo K-medoids, PAM, es una alternativa robusta a k-means para dividir un conjunto de datos en clusters de observación. En el método k-medoids, cada clúster está representado por un objeto seleccionado dentro del clúster. Los objetos seleccionados se denominan medoides y corresponden a los puntos más céntricos central dentro del clúster. La función de R pam() [paquete cluster] puede utilizarse para calcular el algoritmo PAM. El formato simplificado de formato simplificado es pam(x, k), donde “x” son los datos y k es el número de clustersque deben generarse. Después de realizar la agrupación PAM, la función de R fviz_cluster() [paquete factoextra] puede utilizarse para visualizar los resultados. El formato es fviz_cluster(pam.res), donde pam.res es el resultado de PAM.

CLARA - Agrupación de Grandes aplicaciones

Es una extensión de los métodos k-medoides para tratar datos que contienen un gran número de objetos con el fin de reducir el tiempo de cálculo y el problema de almacenamiento de la memoria RAM. Esto se consigue utilizando el enfoque de muestreo.

Computacion de CLARA en R

Formato y preparación de los datos

Aquí, generaremos el uso de un conjunto de datos aleatorios. Para que el resultado sea reproducible, empezamos utilizando la función set. Seed().

set.seed(1234)
# Generate 500 objects, divided into 2 clusters.
df <- rbind(cbind(rnorm(200,0,8), rnorm(200,0,8)),
cbind(rnorm(300,50,8), rnorm(300,50,8)))
# Specify column and row names
colnames(df) <- c("x", "y")
rownames(df) <- paste0("S", 1:nrow(df))
# Previewing the 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

Ahora vamos a installar los siguientes paquetes:

install.packages(c("cluster", "factoextra"))
## Warning: packages 'cluster', 'factoextra' are in use and will not be installed
library(cluster)
library(factoextra)
Estimación del número óptimo de Clusters

En este apartado se vuelve a utilizar el metodo de silueta media.

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

A partir del gráfico, el número de clusters sugerido es 2. En la siguiente sección, clasificaremoslas observaciones en 2 clusters.

Computación en CLARA

El código R siguiente calcula el algoritmo PAM con k = 2:

# Compute CLARA
clara.res <- clara(df, 2, samples = 50, pamLike = TRUE)
# Print components of 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 desea añadir las clasificaciones de puntos a los datos originales, utilice lo siguiente:

dd <- cbind(df, cluster = clara.res$cluster)
head(dd, n = 4)
##             x        y cluster
## S1  -9.656526 3.881815       1
## S2   2.219434 5.574150       1
## S3   8.675529 1.484111       1
## S4 -18.765582 5.605868       1

Puede acceder a los resultados devueltos por clara() como sigue:

# Medoids
clara.res$medoids
##              x         y
## S121 -1.531137  1.145057
## S455 48.357304 50.233499
# Clustering
head(clara.res$clustering, 10)
##  S1  S2  S3  S4  S5  S6  S7  S8  S9 S10 
##   1   1   1   1   1   1   1   1   1   1
Visualización de cluster CLARA

Para visualizar los resultados de la partición, utilizaremos la función fviz_cluster() [factoextrapaquete]. Dibuja un gráfico de dispersión de los puntos de datos coloreados por los números de clúster.

fviz_cluster(clara.res,
palette = c("#00AFBB", "#FC4E07"), # color palette
ellipse.type = "t", # Concentration ellipse
geom = "point", pointsize = 1,
ggtheme = theme_classic()
)

Resumen

El algoritmo CLARA (Clustering Large Applications) es una extensión del método PAM(Partitioning Around Medoids) para grandes conjuntos de datos. Su objetivo es reducir el tiempo de cálculo en el caso de grandes conjuntos de datos. Como casi todos los algoritmos de partición, requiere que el usuario especifique el número adecuado de clústeres que deben producirse. Esto puede estimarse utilizando la función fviz_nbclust [en el paquete R factoextra]. La función R clara() [paquete cluster] puede utilizarse para calcular el algoritmo CLARA. El formato simplificado es clara(x, k, pamLike = TRUE), donde “x” son los datos y k es el número de clusters a generar. Después de calcular CLARA, se puede utilizar la función de R fviz_cluster() [paquete factoextra] para visualizar los resultados. El formato es fviz_cluster(clara.res), donde clara.res es los resultados de CLARA.