Análisis de Clúster (Conglomerados)

Del texto: Joaquin, A. M., & Ezequiel, U. J. (2017). Análisis multivariante aplicado con R. 2a ed. Ediciones Paraninfo, S.A.

3.7 Un ejemplo de aplicación del análisis de conglomerados

Caso 3.3 Diseño de un plan de incentivos para vendedores El director de ventas de una cadena de tiendas de electrodomésticos con implantación nacional está estudiando el plan de incentivos de sus vendedores. Considera que los incentivos deben estar ajustados a las dificultades de las distintas zonas de ventas, siendo necesario fijar incentivos más altos en aquellas zonas geográficas en que las condiciones de vida de sus habitantes hacen más difícil las ventas. Por este motivo quiere determinar si las comunidades autónomas se pueden segmentar en grupos homogéneos respecto al equipamiento de los hogares. Para ello dispone de los datos que aparecen en el cuadro 3.22 y el objetivo es establecer cuántos grupos de comunidades autónomas con niveles de equipamiento similar pueden establecerse y en qué radican las diferencias entre esos grupos.

Cuadro 3.22: Equipamiento de los hogares en distintas comunidades autónomas

Datos_3_3_Caso <- data.frame(
  CCAA = c("Espana", "Andalucia","Aragon","Asturias","Baleares","Canarias","Cantabria", "Castilla y Leon","Castilla-La Mancha","Cataluna","ComValenciana",   "Extremadura","Galicia","Madrid","Murcia","Navarra","Pais Vasco","La Rioja"),
  automovi = c(69.0, 66.7, 67.2, 63.7, 71.9, 72.7, 63.4, 65.8, 61.5, 70.4, 72.7, 60.5, 65.5, 74.0, 69.0, 76.4, 71.3, 64.9),
  tvcolor  = c(97.6, 98.0, 97.5, 95.2, 98.8, 96.8, 94.9, 97.1, 97.3, 98.1, 98.4, 97.7, 91.3, 99.4, 98.7, 99.3, 98.3, 98.6),
  video    = c(62.4, 82.7, 56.8, 52.1, 62.4, 68.4, 48.9, 47.7, 53.6, 71.1, 68.2, 43.7, 42.7, 76.3, 59.3, 60.6, 61.6, 54.4),
  microondas = c(32.3, 24.1, 43.4, 24.4, 29.8, 27.9, 36.5, 28.1, 21.7, 36.8, 26.6, 20.7, 13.5, 53.9, 19.5, 44.0, 45.7, 44.4),
  lavavajillas = c(17.0, 12.7, 20.6, 13.3, 10.1, 5.80, 11.2, 14.0, 7.10, 19.8, 12.1, 11.7, 14.6, 32.3, 12.1, 20.6, 23.7, 17.6),
  telefono = c(85.2, 74.7, 88.4, 88.1, 87.9, 75.4, 80.5, 85.0, 72.9, 92.2, 84.4, 67.1, 85.9, 95.7, 81.4, 87.4, 94.3, 83.4)
)
rownames(Datos_3_3_Caso) <- Datos_3_3_Caso$CCAA
Datos.NbClust <- Datos_3_3_Caso[, -1]

Detección de outliers (Cuadro 3.23)

D2 <- mahalanobis(Datos.NbClust, colMeans(Datos.NbClust), cov(Datos.NbClust))
pval <- pchisq(D2, df = 6, lower.tail = FALSE)
outliers <- data.frame(CCAA = rownames(Datos.NbClust), D2 = round(D2, 2), p_value = round(pval, 2))
outliers
##                                  CCAA    D2 p_value
## Espana                         Espana  0.20    1.00
## Andalucia                   Andalucia 10.52    0.10
## Aragon                         Aragon  1.91    0.93
## Asturias                     Asturias  4.46    0.61
## Baleares                     Baleares  5.70    0.46
## Canarias                     Canarias  9.58    0.14
## Cantabria                   Cantabria  7.29    0.29
## Castilla y Leon       Castilla y Leon  2.21    0.90
## Castilla-La Mancha Castilla-La Mancha  3.54    0.74
## Cataluna                     Cataluna  2.95    0.82
## ComValenciana           ComValenciana  2.65    0.85
## Extremadura               Extremadura 10.43    0.11
## Galicia                       Galicia 13.24    0.04
## Madrid                         Madrid  8.31    0.22
## Murcia                         Murcia  4.88    0.56
## Navarra                       Navarra  7.65    0.26
## Pais Vasco                 Pais Vasco  2.32    0.89
## La Rioja                     La Rioja  4.17    0.65

Clustering jerárquico con varios métodos

matriz.dis.euclid.caso3 <- dist(Datos.NbClust, method = "euclidean")

Estimaríamos ahora los conglomerados por el procedimiento jerárquico. Como debemos evaluar la coherencia de los resultados para decantarnos o descartar alguno de ellos, lo hacemos por todos los métodos de conglomeración que hemos visto entre paréntesis el nombre que tiene la función de la función hclust{stats}- centroide (centroid), vecino más cercano, (single), vecino más lejano (complete), promedio (average), y Ward (ward. D2). La sintaxis, para todos ellos, con la modificación del método sería:

hclust.average.case3<-hclust(matriz.dis.euclid.caso3,method = "average")

/ Hemos de establecer cuántos grupos, pero los dendogramas nos permiten intuir que las comunidades que acabarán en cada grupo van a ser las mismas independientemente del método de conglomeración empleado. Pasamos a la siguiente fase-determinación del número de conglomerados- solo para las tres técnicas que no nos generan dudas respecto a la claridad de los dendogramas: Ward, complete y average.

Aplicamos para ello el procedimiento descrito de generación de índices propuestos por (NbClust) mediante la sintaxis:

Datos.NbClust<-Datos_3_3_Caso[, c("automovi", "tvcolor", "video", "microondas", "lavavajillas", "telefono")]
library(NbClust)
res.wardD2<-NbClust (Datos.NbClust, distance = "euclidean", min.nc=2, max.nc=15, method = "ward.D2", index = "alllong")

## *** : The Hubert index is a graphical method of determining the number of clusters.
##                 In the plot of Hubert index, we seek a significant knee that corresponds to a 
##                 significant increase of the value of the measure i.e the significant peak in Hubert
##                 index second differences plot. 
## 

## *** : The D index is a graphical method of determining the number of clusters. 
##                 In the plot of D index, we seek a significant knee (the significant peak in Dindex
##                 second differences plot) that corresponds to a significant increase of the value of
##                 the measure. 
##  
## ******************************************************************* 
## * Among all indices:                                                
## * 6 proposed 2 as the best number of clusters 
## * 9 proposed 3 as the best number of clusters 
## * 2 proposed 4 as the best number of clusters 
## * 1 proposed 7 as the best number of clusters 
## * 1 proposed 13 as the best number of clusters 
## * 8 proposed 15 as the best number of clusters 
## 
##                    ***** Conclusion *****                            
##  
## * According to the majority rule, the best number of clusters is  3 
##  
##  
## *******************************************************************

Solo cabría sustituir el método de conglomeración para obtener la mejor solución para cada uno de ellos. La aplicación de los criterios es consistente en sus resultados y para cualquier método de conglomeración la solución adecuada es la de 2 conglomerados. Ilustramos la consistencia de los resultados con la evolución para distintos conglomerados del criterio CCC (Sarle, 1983), que, recordemos, alcanzaba su valor máximo para el número óptimo de grupos, que siempre es 2, tal y como se aprecia en la figura 3.12.

Decidido trabajar con una solución de dos grupos que, como mostramos en la figura 3.13, agrupa a las mismas comunidades en los mismos grupos independientemente del método de conglomeración, el paso siguiente es obtener los centroides (valores medios de las 6 variables en cada uno de los dos grupos) con el fin de alimentar con ello el método no jerárquico. Es recomendable dejar que el método no jerárquico los obtenga de manera aleatoria, en la medida en que un punto de partida sensato y el resultado del jerárquico lo es-aumenta las probabilidades de que el proceso de optimización no se estanque en un mínimo local (Milligan, 1980). A partir de este momento ilustraremos el resultado solo con los datos obtenidos del método de conglomeración de Ward.

Generamos una variable que contiene la pertenencia al grupo y la añadimos a la base de datos:

matriz.dis.euclid.caso3 <- dist(Datos.NbClust, method = "euclidean")
hclust.ward.caso3 <- hclust(matriz.dis.euclid.caso3, method = "ward.D2")
hclust.average.case3 <- hclust(matriz.dis.euclid.caso3, method = "average")
hclust.complete.case3 <- hclust(matriz.dis.euclid.caso3, method = "complete")

plot(hclust.ward.caso3, main = "Dendrograma Ward", hang = -1)

grupo.ward<-cutree (hclust.ward.caso3, k=2, h = NULL)
datos.caso3.grupos<-cbind (Datos_3_3_Caso, grupo.ward)
datos.caso3.grupos$id<-NULL

A continuación obtenemos los centroides, que no es otra cosa que la media de las seis variables analizadas en cada uno de los dos grupos obtenidos. El resultado se ofrece en el cuadro 3.24:

round(aggregate (datos.caso3.grupos, list(grupo.ward), mean),2)
##   Group.1 CCAA automovi tvcolor video microondas lavavajillas telefono
## 1       1   NA    66.87   96.82 57.68      25.42        11.81    80.71
## 2       2   NA    70.70   98.53 63.47      44.70        22.43    90.23
##   grupo.ward
## 1          1
## 2          2

Solo resta estimar el análisis de conglomerados no jerárquico tomando como centroides iniciales los anteriores mediante la función kmeans{stats).

cuadro 3.25

grupo.ward <- cutree(hclust.ward.caso3, k = 2)
datos.caso3.grupos <- cbind(Datos_3_3_Caso, grupo.ward)
centroides <- round(aggregate(Datos.NbClust, by = list(grupo = grupo.ward), mean), 2)
print(centroides)
##   grupo automovi tvcolor video microondas lavavajillas telefono
## 1     1    66.87   96.82 57.68      25.42        11.81    80.71
## 2     2    70.70   98.53 63.47      44.70        22.43    90.23
c1 <- centroides[1, -1]
c2 <- centroides[2, -1]
solucion <- kmeans(Datos.NbClust, centers = rbind(c1, c2))
print(solucion$cluster)
##             Espana          Andalucia             Aragon           Asturias 
##                  1                  1                  2                  1 
##           Baleares           Canarias          Cantabria    Castilla y Leon 
##                  1                  1                  1                  1 
## Castilla-La Mancha           Cataluna      ComValenciana        Extremadura 
##                  1                  2                  1                  1 
##            Galicia             Madrid             Murcia            Navarra 
##                  1                  2                  1                  2 
##         Pais Vasco           La Rioja 
##                  2                  2

El cuadro 3.25 recoge la salida, donde, como se puede comprobar, al ser un caso con pocos datos, la solución del jerárquico coincide con la del no jerárquico.

FIGURA 3.13

CUADRO 3.25

Antes de interpretar las medias, conviene saber cuáles son significativamente diferentes entre los grupos. En temas posteriores se presentará el análisis de la varianza de un factor, que sería la herramienta que conviene aplicar para este fin si tuviéramos más de dos grupos. Al tener solo dos grupos, podemos aplicar una prueba t, con la siguiente sintaxis para cada variable dependiente:

Cuadro 3.26

library(dplyr)
Datos_t <- Datos.NbClust %>% mutate(grupo = solucion$cluster)

resultados_t <- sapply(names(Datos.NbClust), function(var){
  t <- t.test(Datos_t[[var]] ~ Datos_t$grupo)
  c(t$statistic, t$p.value)
})
t_resultados <- data.frame(t(resultados_t))
colnames(t_resultados) <- c("t", "p_value")
round(t_resultados, 3)
##                   t p_value
## automovi     -1.811   0.100
## tvcolor      -2.515   0.024
## video        -1.189   0.255
## microondas   -6.734   0.000
## lavavajillas -4.605   0.003
## telefono     -3.508   0.003

En el ejemplo ilustrado vemos como el porcentaje de la población que tiene automóvil en el primer grupo de comunidades autónomas es (66,86%) inferior al del segundo grupo (70,70%), aunque esta diferencia no es significativa (t=-1,81; p > 0,05). Para facilitar el análisis general, llevamos todos los resultados al cuadro 3.26. A la luz del mismo podemos concluir que el grupo 2 se corresponde con comunidades autónomas donde los equipamientos son significativamente superiores, probablemente debido a una mayor renta per cápita.

Aunque veremos la herramienta con mayor detalle en el tema correspondiente, una manera de intentar visualizar los resultados de un análisis de conglomerados, más allá de los dendogramas, es sintetizar todas las variables en dos componentes principales y proyectar sobre ellos los objetos. La figura 3.14 mues-tra el claro nivel de separación entre los dos grupos que ya hemos interpretado.

En el tema correspondiente veremos cómo interpretar los ejes

Figura 3.14

pca <- prcomp(Datos.NbClust, scale. = TRUE)
plot(pca$x[,1:2], col = solucion$cluster, pch = 19,
     xlab = "PC1", ylab = "PC2", main = "Proyeccion PCA por grupo")
text(pca$x[,1:2], labels = rownames(Datos.NbClust), pos = 3)