Descripción de la técnica

El análisis de conglomerados corresponde a un conjunto de técnicas que permite clasificar observaciones (casos) en grupos relativamente homogeneos internamente y, al mismo tiempo, relativamente diferentes entre ellos. A estos grupos se les denomina clusters o conglomerados. Este tipo de análisis multivariado es de caracter exploratorio y descriptivo.

En particular, el análisis de conglomerados K-Means es un método de agrupamiento que busca la partición de un conjunto de observaciones (n) en K grupos o conglomerados, en donde cada observación será asignada al grupo cuyo valor medio sea más cercano.

Librerias a utilizar

Para la realización de este análisis, se utilizarán las siguientes paqueterías: haven para importar bases de datos en formato .sav (SPSS), dplyr y tidyr para la manipulación y transformación de la data, el paquete factoextra, que nos permitirá realizar el análisis de conglomerados K-Means. Además, trabajaremos con el paquete NbClust, el cuál nos entregará una serie de indicadores para decidir la cantidad de conglomerados a generar y, finalmente, el paquete expss con el que realizaremos una tabla de comparación de medias con ajuste de bonferroni para caracterizar a nuestros conglomerados.

library(haven)
library(dplyr)
library(tidyr)
library("factoextra")
library(NbClust)
library(expss)
library(tibble)
library(gridExtra)

Cargar y explorar datos

Para el ejercicio, utilizaremos la base de datos del estudio Voces Constituyentes, realizado de manera conjunta por las empresas que conforman la Asociación de Investigadores de Mercado y Opinión Pública (AIM). Dicho estudio corresponde a una encuesta web dirigida a hombres y mujeres mayores de 18 años, pertenecientes a todos los grupos socioeconómicos (GSE) y residentes de todas las regiones del país, quienes se registraron voluntariamente para responder encuestas online en diferentes paneles web.

base <- read_sav("raw/BBDD_Voces_Ciudadanas_AIM2021 final.sav")

Selección de variables a considerar

Las variables a considerar corresponden a una batería de 3 preguntas que buscan que cada encuestado se posicione en un eje político de izquierda (0) a derecha (10), un eje valórico o cultural que va de conservador (0) a liberal (10) y un eje económico, que se mueve de pro-mercado (0) a pro-regulación estatal (10). Todas las variables se encuentran en la misma escala, por lo que no será necesario estandarizarlas para el análisis.

base_active <- base %>% select(P21_1,P22_1,P23_1)

Análisis exploratorio de los datos

Al realizar un análisis descriptivo univariado, observamos que la categoría de no respuesta tiene asociado el código 88, lo que distorsiona las medidas de tendencia central de las variables en cuestión. Esto resultará problemático para el análisis propuesto, por lo que se debe tomar una decisión metodológica respecto a cómo proceder con esos casos al momento de realizar el análisis.

summary(base_active)
##      P21_1           P22_1           P23_1      
##  Min.   : 0.00   Min.   : 0.00   Min.   : 0.00  
##  1st Qu.: 4.00   1st Qu.: 3.00   1st Qu.: 5.00  
##  Median : 5.00   Median : 5.00   Median : 7.00  
##  Mean   :17.65   Mean   :13.05   Mean   :11.56  
##  3rd Qu.: 8.00   3rd Qu.: 9.00   3rd Qu.: 9.00  
##  Max.   :88.00   Max.   :88.00   Max.   :88.00

Preparar data para el análisis

Previo a la realización del análisis, debemos preparar nuestro conjunto de datos. Como todas las variables se encuentran en la misma escala, no será necesaria estandarizarlas. Aun así, es pertinente resolver qué hacer con los casos que respondieron “No sabe” en cada una de las 3 variables consideradas. Una posible alternativa, es considerar dichas variables como “valores perdidos” y excluirlos del análisis. Sin embargo, ello obvia que la no respuesta es una categoría de respuesta válida (no es un dato perdido, es una posición) y, además, que pueden representar algún patrón de respuesta capaz de conformar un propio conglomerado. Por ello, se decide mantener esos casos en el análisis, pero recodificar su valor (88 actualmente) a 11, de manera de no distorsionar el plano de dos dimensiones sobre el que se proyectarán los casos.

base_active$P21_1[base_active$P21_1 == 88] <- 11
base_active$P22_1[base_active$P22_1 == 88] <- 11
base_active$P23_1[base_active$P23_1 == 88] <- 11

Además, se debe revisar que nuestras observaciones no cuenten con valores perdidos para las variables consideradas. Si ese fuera el caso, se deberán excluir dichas observaciones del análisis o imputar el valor perdido. En nuestro caso, eliminaremos dichos casos.

base_active <- na.omit(base_active) #No se elimina nada porque ningun caso tiene valores perdidos

Criterios para determinar número optimo de clusters

Existen diversos criterios para determinar el número óptimo de conglomerados a generar. A modo de ejemplo, vamos a revisar 3 de ellos para constatar las dificultades que pueden derivar de apoyarse en uno u otro.

En primer lugar, el método de “codo” (elbow method) calcula la suma de las distancias al cuadrado de cada punto hacia su centro asignado. Este método sugiere como óptimo aquel valor de k (cantidad de conglomerados) a partir del cual añadir un conglomerado adicional apenas consigue mejoría, como sucede al pasar de K=6 a K=7.

fviz_nbclust(base_active, kmeans, method = "wss") +
  labs(title = "Método Elbow - Número optimo de conglomerados")

El estadístico Gap, por otro lado, compara para diferentes valores de k (cantidad de conglomerados), la varianza total intra-cluster frente al valor esperado acorde a una distribución uniforme de referencia, siendo un número óptimo de conglomerados el valor de k con el que se consigue una estructura de clusters lo más alejada posible de la distribución uniforme aleatoria considerada. Dicho método sugiere 2 clusters

fviz_nbclust(base_active, kmeans,iter.max = 100,
             method = "gap_stat") +
  labs(title = "Método estadístico Gap - Número optimo de conglomerados")

Otra alternativa corresponde al método Silhouette, que cuantifica cuan buena es la asignación de una observación a un conglomerado comparando su similitud con el resto de observaciones de dicho conglomerado frente a las de los otros conglomerados. Este método sugiere una solución de K=7.

fviz_nbclust(base_active, kmeans,iter.max = 100,
             method = "silhouette") +
  labs(title = "Método Silhouette - Número optimo de conglomerados")

Como vemos, los diferentes métodos observados sugieren soluciones óptimas diferentes, entregando orientaciones que no coinciden para efectos de definir nuestro hiperparametro K. Tal como estos criterios, existen numerosos otros que nos pueden sugerir incluso diferentes soluciones óptimas. Por ello, podemos recurrir a la función NbClust que revisa 26 criterios diferentes y nos entrega una recomendación por “regla de mayoría”, esto es, la cantidad de conglomerados sugerida por la mayor cantidad de métodos considerados.

Si bien corresponde a una buena estrategia para acotar el rango de posibilidades, siempre será relevante evaluar la cantidad de conglomerados obtenidos a la luz de su pertinencia teórica.

###26 indices para determinar numero de clusters
set.seed(123)
res.nbclust <- NbClust(base_active, distance = "euclidean",
                       min.nc = 2, max.nc = 9, 
                       method = "kmeans", index ="all") 

## *** : 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:                                                
## * 4 proposed 2 as the best number of clusters 
## * 3 proposed 3 as the best number of clusters 
## * 7 proposed 4 as the best number of clusters 
## * 4 proposed 5 as the best number of clusters 
## * 5 proposed 9 as the best number of clusters 
## 
##                    ***** Conclusion *****                            
##  
## * According to the majority rule, the best number of clusters is  4 
##  
##  
## *******************************************************************

Para revisar el resumen de todos los métodos o criterios revisados por NbClust.

#Revisar todos los indices
res.nbclust$All.index
##       KL       CH Hartigan     CCC     Scott      Marriot    TrCovW   TraceW
## 2 1.2919 1214.657 611.9866 48.5600  9742.725 3.303903e+13 550487856 65520.65
## 3 0.9436 1042.418 903.4109 39.6868 10903.062 4.963734e+13 323892263 54008.19
## 4 3.5918 1214.412 541.1907 41.1821 13848.443 3.165556e+13 226276317 41077.82
## 5 0.8123 1217.491 276.4694 49.9831 14924.093 3.401499e+13 133767780 34558.85
## 6 0.8592 1122.786 421.6326 46.2957 15760.712 3.660716e+13 108418880 31520.35
## 7 1.0853 1143.130 371.3498 48.0079 16681.211 3.616707e+13  82933045 27479.16
## 8 3.0280 1159.428 268.5579 49.7310 17738.306 3.269658e+13  64309165 24327.08
## 9 0.4985 1142.766 278.6282 49.9091 18536.466 3.134399e+13  48949377 22242.15
##   Friedman   Rubin Cindex     DB Silhouette   Duda  Pseudot2   Beale Ratkowsky
## 2  18.1189  6.0408 0.3385 1.5336     0.2817 1.0691 -131.5506 -0.1100    0.2997
## 3  19.6891  7.3285 0.3258 1.4786     0.2626 1.1301 -111.4630 -0.1957    0.3656
## 4  30.5161  9.6353 0.2875 1.3354     0.2971 1.4686 -341.7344 -0.5421    0.3606
## 5  33.3953 11.4528 0.3191 1.2112     0.3083 2.0242 -554.0340 -0.8594    0.3488
## 6  37.3977 12.5569 0.2933 1.2552     0.2628 1.8025 -391.7971 -0.7561    0.3278
## 7  40.9233 14.4035 0.3186 1.1760     0.2784 1.4725 -183.8590 -0.5448    0.3153
## 8  46.8692 16.2698 0.2829 1.1252     0.2997 1.2311 -105.6872 -0.3187    0.3023
## 9  51.8166 17.7949 0.2741 1.0941     0.3132 1.2214  -90.8169 -0.3077    0.2896
##        Ball Ptbiserial    Frey McClain   Dunn Hubert SDindex Dindex   SDbw
## 2 32760.327     0.3955  0.1842  0.6850 0.0556      0  0.7284 4.3751 1.8781
## 3 18002.729     0.4695  0.1600  1.0711 0.0609      0  0.6984 3.9623 1.3647
## 4 10269.455     0.5145  0.4418  1.3740 0.0609      0  0.5908 3.4166 0.7289
## 5  6911.770     0.5024  0.9011  1.8335 0.0747      0  0.5829 3.1515 0.6543
## 6  5253.392     0.4655  0.3780  2.3411 0.0718      0  0.6517 2.9838 0.8272
## 7  3925.594     0.4506 -0.0729  2.7349 0.0828      0  0.6026 2.8293 0.6406
## 8  3040.885     0.4895  0.1124  2.5846 0.0828      0  0.7349 2.6275 0.7901
## 9  2471.351     0.4924  0.2803  2.6436 0.0842      0  0.6905 2.5125 0.4061

Finalmente, podemos revisar como tabla el resultado del análisis. La primera columna nos señala el valor del hiperparametro K. La segunda nos indica la cantidad de métodos/criterios que sugieren cada uno de esos valores de K. El criterio, por tanto, será escoger aquel valor de K con la mayor cantidad de recomendaciones (con el “n” más alto en la tabla).

#Ver como tabla
res.nbclust$Best.nc %>% 
  as.tibble() %>% 
  slice(1) %>% 
  pivot_longer(1:26) %>% 
  count(value)
## Warning: `as.tibble()` was deprecated in tibble 2.0.0.
## Please use `as_tibble()` instead.
## The signature and semantics have changed, see `?as_tibble`.
## # A tibble: 7 x 2
##   value     n
##   <dbl> <int>
## 1     0     2
## 2     1     1
## 3     2     4
## 4     3     3
## 5     4     7
## 6     5     4
## 7     9     5

Ello también se puede observar visualmente.

#Frecuencia de cantidad de clusters recomendados por el conjunto de indices
factoextra::fviz_nbclust(res.nbclust) + theme_minimal()
## Among all indices: 
## ===================
## * 2 proposed  0 as the best number of clusters
## * 1 proposed  1 as the best number of clusters
## * 4 proposed  2 as the best number of clusters
## * 3 proposed  3 as the best number of clusters
## * 7 proposed  4 as the best number of clusters
## * 4 proposed  5 as the best number of clusters
## * 5 proposed  9 as the best number of clusters
## 
## Conclusion
## =========================
## * According to the majority rule, the best number of clusters is  4 .

Generar y analizar clusters

La solución de 4 conglomerados corresponde a la que concentra la mayor cantidad de recomendaciones por los 26 criterios revisados. Además, a modo de ejemplo, revisaremos también los resultados asociados a una solución con solo 2 conglomerados. Para generar ambas soluciones, utilizaremos el comando kmeans especificando la data a utilizar, el número de conglomerados solicitados, la cantidad máxima de iteraciones para converger, y la cantidad de puntos iniciales con los que partirá el análisis. Además, para la replicabilidad del ejercicio, se utiliza el comando set.seed para fijar la “semilla” inicial en torno a los puntos pseudoaleatorios sobre los que se posicionarán los 25 puntos iniciales.

set.seed(123)
km.res_4 <- kmeans(base_active, 4, #Numero de clusters
                   iter.max = 100,  #Numero de iteraciones máxima
                   nstart = 25) #Numero de puntos iniciales

set.seed(123)
km.res_2 <- kmeans(base_active, 2, #Numero de clusters
                 iter.max = 100,  #Numero de iteraciones máxima
                 nstart = 25) #Numero de puntos iniciales

Para observar un resumen de la solución de 4 conglomerados podemos utilizar el siguiente comando. Dicho resumen nos entrega los pesos de cada conglomerado, las medias por conglomerado para las variables consideradas, nos muestra un vector con el conglomerado de pertenencia de cada observación, entre otras medidas.

print(km.res_4) #Mostrar resumen 
## K-means clustering with 4 clusters of sizes 603, 1049, 509, 712
## 
## Cluster means:
##       P21_1    P22_1    P23_1
## 1  4.920398 2.323383 8.248756
## 2  5.813155 3.980934 3.464252
## 3 10.229862 8.899804 8.245580
## 4  2.821629 8.512640 8.018258
## 
## Clustering vector:
##    [1] 3 3 2 3 3 1 4 2 2 2 2 2 2 3 3 3 3 2 1 2 1 3 4 4 4 4 4 1 2 2 2 2 1 2 4 1 2
##   [38] 4 2 1 4 4 4 4 4 2 4 2 2 2 2 3 2 4 4 1 2 1 4 2 1 4 4 4 2 4 3 2 4 1 3 3 3 3
##   [75] 2 4 2 3 4 3 2 1 3 3 3 3 1 4 4 2 1 2 2 2 1 2 1 4 1 1 2 4 4 2 1 2 2 1 2 1 2
##  [112] 4 3 1 3 3 1 2 3 4 4 3 3 4 3 2 2 2 3 3 1 4 2 3 2 4 4 4 2 3 2 2 2 3 3 3 2 4
##  [149] 3 1 1 1 2 2 1 2 2 2 2 3 1 2 2 3 2 1 2 2 2 2 1 2 4 2 3 4 3 2 4 2 4 4 2 2 4
##  [186] 4 2 2 4 4 4 4 4 4 2 3 2 4 4 1 1 1 1 2 1 3 2 1 4 2 3 2 2 2 2 2 3 1 3 4 3 1
##  [223] 1 4 2 4 2 1 3 4 2 2 4 3 3 4 2 3 3 2 2 2 2 3 1 2 2 4 4 2 1 2 4 2 1 1 1 1 2
##  [260] 3 2 2 4 4 2 1 1 4 1 4 2 2 2 2 1 4 2 2 2 2 2 2 3 4 4 3 3 2 4 3 3 2 1 3 4 2
##  [297] 4 2 1 4 2 4 4 1 2 4 1 4 4 4 1 4 3 4 4 3 2 1 1 2 3 4 1 3 2 2 3 2 2 2 2 1 1
##  [334] 2 2 3 3 2 2 3 2 2 2 4 2 1 4 3 2 2 4 2 2 1 2 1 1 2 4 2 2 1 2 3 4 4 1 2 3 3
##  [371] 4 1 2 3 2 4 4 1 4 1 2 2 2 4 4 2 2 4 2 2 1 2 3 2 3 1 1 4 4 2 4 1 2 2 2 3 2
##  [408] 1 4 2 2 4 4 4 4 4 2 4 4 4 4 1 1 1 1 2 1 2 2 2 2 2 2 2 2 2 4 2 2 4 2 2 2 2
##  [445] 2 2 2 2 1 2 3 3 2 2 4 4 2 1 2 1 3 2 1 2 2 2 3 2 2 2 1 1 2 2 4 2 4 1 2 4 2
##  [482] 4 2 2 2 4 3 4 3 1 2 1 1 3 3 4 2 2 4 1 2 2 4 3 3 2 1 1 2 2 2 2 2 3 1 1 3 2
##  [519] 2 1 3 3 3 4 4 4 2 4 4 4 4 4 4 2 4 2 4 2 2 4 1 2 2 2 4 4 3 2 2 4 4 4 2 1 1
##  [556] 2 1 3 2 2 2 2 2 2 4 2 1 1 2 2 1 4 4 2 1 3 2 3 2 3 2 3 1 1 1 2 4 3 2 4 2 2
##  [593] 2 4 4 1 2 2 4 1 2 2 2 4 2 2 4 2 4 4 4 2 2 1 4 2 3 2 3 1 4 1 2 4 4 1 1 1 3
##  [630] 3 1 2 2 2 2 3 4 3 2 4 4 4 3 4 1 2 2 1 4 4 4 4 4 4 1 4 4 4 4 4 4 4 2 4 4 4
##  [667] 1 4 3 3 1 2 1 2 2 2 3 4 4 4 2 4 2 4 4 4 4 4 4 4 4 4 4 4 3 3 2 4 3 2 1 2 1
##  [704] 4 4 4 2 4 4 4 1 3 1 1 1 4 1 4 4 2 3 4 4 4 4 2 3 2 1 2 4 4 4 4 1 4 4 4 3 1
##  [741] 2 4 1 1 2 1 1 3 2 2 3 3 4 1 2 2 4 1 4 2 4 3 2 3 4 4 1 3 4 1 2 3 4 1 4 2 2
##  [778] 1 2 4 4 2 2 4 4 1 3 4 2 3 4 1 1 2 3 3 2 2 2 4 1 4 1 4 3 4 2 2 4 2 4 4 2 3
##  [815] 1 4 1 4 4 4 1 2 2 2 4 4 2 2 2 4 4 2 2 2 1 3 4 4 4 2 1 1 2 2 3 1 2 1 2 4 4
##  [852] 2 2 1 4 4 3 3 1 2 2 3 1 2 3 3 4 2 2 1 1 2 1 4 2 4 1 4 2 2 1 2 2 2 2 2 3 2
##  [889] 2 2 2 2 1 1 2 2 3 2 1 2 3 4 1 3 4 3 4 3 1 2 4 2 1 3 3 3 1 3 2 2 1 1 4 2 2
##  [926] 1 2 4 2 4 2 4 4 4 4 4 2 2 2 1 2 2 4 3 3 2 4 4 2 1 4 4 3 1 1 3 4 1 1 2 2 2
##  [963] 2 3 4 2 2 2 3 1 2 3 2 3 3 4 3 4 3 4 2 4 2 4 4 4 1 4 4 1 1 3 1 1 2 1 4 4 4
## [1000] 1 4 4 3 2 4 4 3 3 1 4 2 4 2 4 4 2 1 4 2 1 4 4 1 1 1 4 3 1 1 4 4 1 1 4 4 4
## [1037] 3 3 1 1 2 2 3 2 4 2 2 2 4 4 2 2 2 2 3 2 2 1 1 3 1 3 1 3 1 3 2 1 4 3 2 4 1
## [1074] 4 3 1 2 2 2 2 2 3 4 4 2 3 3 2 3 3 2 3 4 2 2 1 1 1 4 4 1 2 2 2 4 4 4 3 1 2
## [1111] 4 3 2 3 1 1 1 2 4 1 2 2 2 1 2 4 4 2 1 2 1 1 3 2 4 2 4 2 3 1 2 3 4 4 2 2 3
## [1148] 4 2 2 2 1 2 2 4 3 1 2 3 2 2 2 2 1 2 2 2 3 2 1 3 2 4 2 1 1 2 2 4 2 3 2 1 1
## [1185] 2 2 2 2 4 1 4 1 1 2 1 2 1 2 2 2 2 2 2 3 3 2 1 2 2 2 1 2 2 4 4 4 2 2 1 2 4
## [1222] 2 1 2 1 1 3 3 4 4 2 4 2 2 3 2 1 1 2 2 3 2 3 4 4 2 3 4 3 2 4 4 2 4 4 2 1 2
## [1259] 2 2 2 2 1 1 3 4 4 2 3 4 2 2 3 2 3 2 1 2 2 2 1 2 1 2 2 3 2 2 2 1 3 3 4 2 2
## [1296] 1 2 4 2 2 4 1 3 4 4 2 2 1 1 3 3 3 2 3 3 2 2 2 1 2 2 1 2 4 2 1 2 4 3 3 1 1
## [1333] 1 1 3 3 3 2 2 2 3 4 4 4 2 1 2 2 2 2 2 4 2 2 3 2 4 2 2 3 1 2 1 4 4 4 2 4 1
## [1370] 4 4 4 2 4 2 4 4 1 2 2 1 4 2 2 2 1 4 2 2 1 4 2 4 3 2 2 3 4 2 3 2 4 1 2 2 2
## [1407] 2 1 1 4 2 1 4 4 4 1 1 4 2 2 3 2 2 2 2 2 2 1 4 2 4 4 2 2 1 4 1 4 3 4 1 2 1
## [1444] 4 2 4 2 1 1 1 3 2 2 2 4 1 2 2 2 2 4 2 4 2 1 4 2 1 2 3 4 1 1 1 1 2 1 2 1 4
## [1481] 2 1 1 3 3 3 2 1 2 2 2 2 3 2 4 4 4 1 4 3 2 3 2 2 2 2 2 4 1 1 2 4 1 2 2 3 1
## [1518] 4 1 2 3 4 1 3 2 2 2 4 4 4 2 4 4 2 3 3 3 3 3 4 3 4 3 3 2 4 1 3 3 2 4 1 2 3
## [1555] 1 3 2 2 3 2 3 3 2 1 2 1 3 2 2 2 2 2 3 4 3 2 3 2 2 4 4 4 4 1 2 2 4 2 4 4 1
## [1592] 1 2 2 3 2 2 3 1 1 3 1 2 2 3 1 1 2 1 1 1 4 3 4 2 2 1 3 1 3 4 2 1 4 4 4 2 4
## [1629] 4 3 2 2 3 4 3 2 3 1 3 2 2 4 2 1 1 1 2 1 2 1 2 2 1 1 3 2 2 2 1 3 1 3 1 1 3
## [1666] 2 3 2 2 2 1 2 2 3 2 2 4 1 1 2 2 1 2 4 1 2 2 4 2 2 2 3 3 3 1 1 2 2 4 3 1 3
## [1703] 2 4 4 2 3 3 2 1 4 1 2 1 4 3 4 3 1 3 2 2 4 1 2 4 4 3 1 3 1 4 4 4 2 1 1 2 1
## [1740] 2 3 4 1 2 4 2 2 3 2 2 2 4 2 4 1 2 2 2 4 1 1 2 4 2 3 2 2 4 4 4 4 1 4 2 2 1
## [1777] 1 1 1 1 4 2 2 1 1 4 2 1 1 2 4 2 2 4 2 2 4 4 2 1 2 4 2 2 3 2 2 4 1 1 1 4 3
## [1814] 1 3 2 4 3 4 4 1 2 1 3 2 4 4 4 4 3 4 2 3 3 4 4 3 1 3 4 1 1 4 1 2 2 4 4 4 4
## [1851] 2 2 2 1 3 2 4 4 1 4 4 4 1 2 4 1 4 1 1 2 1 2 2 3 3 2 2 3 2 2 1 2 4 2 1 4 4
## [1888] 1 1 4 2 3 1 4 1 3 1 4 4 1 3 1 2 4 3 1 4 4 3 2 3 2 2 1 4 4 4 2 1 4 3 4 1 4
## [1925] 2 2 4 1 3 3 1 1 2 2 3 2 1 1 4 1 1 4 2 3 2 1 2 2 2 4 3 2 3 4 3 2 1 1 4 3 4
## [1962] 1 4 4 4 2 4 3 1 1 4 4 3 1 4 4 4 4 2 1 4 4 1 4 4 3 4 4 4 2 2 2 3 1 4 4 1 2
## [1999] 4 2 1 3 4 1 4 4 1 1 1 4 2 4 1 2 4 2 3 1 2 3 2 4 2 3 1 1 2 1 3 1 4 4 1 4 1
## [2036] 2 1 2 1 1 3 2 2 3 1 3 1 1 3 1 2 2 4 2 1 2 1 2 1 1 4 2 3 2 2 4 2 1 2 2 2 2
## [2073] 4 2 2 3 4 2 1 1 1 1 1 2 2 2 1 3 1 3 3 1 1 3 4 3 2 3 1 3 3 2 2 3 2 2 1 2 2
## [2110] 1 2 2 2 2 3 2 4 3 3 1 3 1 3 3 2 3 2 2 2 4 3 1 4 4 3 2 4 1 1 4 2 4 2 4 2 1
## [2147] 1 4 4 4 2 4 2 2 3 2 2 2 3 2 2 2 2 1 4 2 2 3 3 4 1 4 3 1 1 1 1 4 1 2 2 3 1
## [2184] 3 2 3 4 1 2 2 2 2 3 2 4 2 4 1 2 3 2 2 1 3 2 3 2 2 4 3 2 2 2 3 2 2 1 2 4 2
## [2221] 4 1 1 4 2 3 4 2 4 4 2 2 2 1 3 2 2 4 2 2 4 4 1 1 4 1 1 1 3 3 2 3 3 3 3 3 2
## [2258] 2 1 2 1 2 1 2 2 2 2 3 1 2 4 4 2 4 2 2 1 2 2 2 1 3 2 2 3 1 1 3 3 2 2 1 2 3
## [2295] 1 1 2 3 1 1 1 2 4 1 3 3 4 1 2 4 2 2 2 4 2 1 4 1 4 3 3 2 2 3 2 3 4 2 1 4 2
## [2332] 1 2 4 4 4 3 1 1 4 1 2 4 3 2 2 2 2 2 2 2 2 1 3 1 2 2 2 2 2 4 3 2 4 4 2 1 4
## [2369] 4 4 1 3 3 1 3 1 3 2 1 2 1 3 4 2 1 1 3 2 3 2 2 2 4 2 3 3 4 1 2 4 2 2 2 3 3
## [2406] 1 4 2 2 1 1 2 1 1 2 2 3 3 2 4 4 2 4 2 1 1 2 2 2 4 4 4 3 2 2 2 2 2 2 2 2 1
## [2443] 2 4 3 2 2 3 1 4 4 2 4 4 4 2 2 2 1 1 3 4 4 4 4 2 3 1 4 2 4 2 2 2 2 4 4 2 1
## [2480] 4 1 4 3 2 2 4 3 4 1 1 1 1 4 4 2 4 4 2 1 2 3 3 4 1 2 1 4 1 4 1 3 1 3 1 3 2
## [2517] 1 3 3 2 2 4 3 2 2 1 4 3 1 4 3 4 2 3 1 4 2 2 3 4 4 2 4 4 2 2 1 1 3 2 1 2 2
## [2554] 1 2 2 1 4 2 3 1 2 4 2 1 3 2 3 2 4 3 2 4 2 4 4 4 4 4 4 2 4 2 2 3 3 4 2 1 1
## [2591] 2 3 2 4 2 2 2 3 4 1 3 1 4 2 2 4 2 1 1 4 2 1 4 1 2 3 2 1 2 4 4 2 4 2 2 2 4
## [2628] 3 2 2 2 3 2 1 4 2 2 1 4 2 4 3 1 2 4 1 2 4 3 2 1 2 1 3 2 2 4 1 4 1 2 1 4 2
## [2665] 1 3 1 1 2 2 1 2 2 2 2 2 3 3 4 2 3 2 1 4 2 2 4 4 3 4 4 4 1 3 3 2 1 2 4 3 4
## [2702] 4 2 3 2 1 1 1 2 3 2 3 2 4 2 1 1 4 1 2 2 1 3 3 4 1 4 4 1 3 4 3 4 3 4 1 2 4
## [2739] 4 1 3 3 3 2 2 1 3 3 3 1 1 2 1 2 4 3 3 2 2 4 1 2 1 2 1 2 4 4 2 2 2 3 4 3 2
## [2776] 4 3 3 3 3 4 3 2 2 2 2 3 4 2 2 1 4 1 2 3 2 1 2 1 3 3 1 1 2 3 3 4 3 2 1 1 1
## [2813] 3 2 4 2 2 4 2 1 2 4 2 3 3 3 3 3 3 3 3 3 2 3 1 3 4 4 3 1 2 4 2 2 3 3 3 2 3
## [2850] 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3 2 1 2 2 3
## 
## Within cluster sum of squares by cluster:
## [1]  8964.806 17117.907  7248.299  7690.996
##  (between_SS / total_SS =  56.0 %)
## 
## Available components:
## 
## [1] "cluster"      "centers"      "totss"        "withinss"     "tot.withinss"
## [6] "betweenss"    "size"         "iter"         "ifault"

Además, podemos solicitar información adicional, como la suma de cuadrados intra-conglomerado.

km.res_4$withinss  
## [1]  8964.806 17117.907  7248.299  7690.996

La suma total de cuadrados dentro de cada conglomerado.

km.res_4$tot.withinss
## [1] 41022.01

La suma total de cuadrados

km.res_4$totss
## [1] 93241

La suma de cuadrados entre grupos.

km.res_4$betweenss
## [1] 52219

La cantidad de iteraciones realizada.

km.res_4$iter
## [1] 5

Finalmente, podemos observar como nube de puntos (o scatter plot) los conglomerados conformados.

km_clusters_2 <-fviz_cluster(object = km.res_2, data = base_active, show.clust.cent = TRUE,
             ellipse.type = "euclid", star.plot = FALSE, repel = FALSE, labelsize = 0) +
  theme_bw()+
  labs(title = "Resultados K-Means con k=2")

km_clusters_4 <-fviz_cluster(object = km.res_4, data = base_active, show.clust.cent = TRUE,
                           ellipse.type = "euclid", star.plot = FALSE, repel = FALSE, labelsize = 0) +
  theme_bw()+
  labs(title = "Resultados K-Means con k=4")

grid.arrange(km_clusters_2,km_clusters_4, nrow = 2)

Además, vamos a añadir a la base de datos original una variable adicional con el conglomerado de pertenencia para cada observación. Esta variable nos permitirá caracterizar mejor estos conglomerados y podremos utilizarla para otro tipo de análisis. Añadiremos dos variables, una para cada solución probada (de 2 y 4 conglomerados).

data_cluster_2 <- km_clusters_2$data
data_cluster_4 <- km_clusters_4$data
base <- base %>% mutate(cluster_2 = data_cluster_2$cluster,
                        cluster_4 = data_cluster_4$cluster,)

Para terminar, realizaremos una tabla que nos permita contrastar las medias para cada una de nuestras variables de interes, utilizando un test de comparación de medias con ajuste de bonferroni. Para ello, recurriremos al paquete expss. Además, para efectos de este ejercicio, vamos a considerar como valor perdido las respuestas “No sabe” (codificadas en la base original como 88). Esto nos permitirá caracterizar y comprender mejor nuestros conglomerados.

var_lab(base$P21_1) = "Eje Izquierda-Derecha"
var_lab(base$P22_1) = "Eje Mercado-Estado"
var_lab(base$P23_1) = "Eje Conservador-Liberal"

banner <- base %>% tab_cols(total(), cluster_2,cluster_4) %>% #Se debe crear el objeto Banner, con las variables de cruce a considetat y la función total()
  tab_weight(weight = Ponderador) #Con tab_weight se pone la variable ponderador

tab_means_sig = . %>% tab_stat_mean_sd_n(labels = c("Mean", "sd", "N")) %>% 
  tab_last_sig_means(bonferroni = TRUE)

banner %>% 
  tab_cells(P21_1) %>%
  tab_mis_val(88) %>%
  tab_means_sig %>%
  tab_cells(P22_1) %>%
  tab_mis_val(88) %>%
  tab_means_sig %>%
  tab_cells(P23_1) %>%
  tab_mis_val(88) %>%
  tab_means_sig %>%
  tab_pivot()
 #Total     cluster_2     cluster_4 
   1     2     1     2     3     4 
   A     B     A     B     C     D 
 Eje Izquierda-Derecha 
   Mean  4.9    4.4    5.2 A   4.7 D   5.5 A D   8.7 A B D   2.9 
   sd  2.7    2.9    2.5     2.4     2.3     1.2     1.9 
   N  2426.0    982.0    1444.0     562.0     993.0     159.0     712.0 
 Eje Mercado-Estado 
   Mean  5.0    8.1 B   3.2    2.2    4.0 A   7.5 A B   8.2 A B C
   sd  3.1    1.7     2.2    2.1    2.4     2.1     1.5  
   N  2596.0    1001.0     1595.0    603.0    1046.0     305.0     642.0  
 Eje Conservador-Liberal 
   Mean  5.9    7.3 B   5.0    8.1 B C   3.5    7.0 B   7.8 B C
   sd  2.9    2.7     2.7    1.6     1.9    2.4     2.1  
   N  2682.0    1108.0     1574.0    579.0     1049.0    363.0     691.0  

Los resultados nos muestran que una solución de 2 conglomerados divide a los encuestados en grupos que podríamos denominar “centro-izquierda tradicional” y “centro-derecha tradicional”. El primer grupo, se encuentra más a la izquierda (con un promedio de 4.4), se inclina por mayor regulación estatal (prom=8.1) y se identifica como liberal (prom=7.3). El segundo grupo es el opuesto perfecto: más inclinado hacia la derecha (prom=5.2), a favor del libre mercado (prom=3.2) y en una posición más intermedia en la escala liberal-conservador (prom=5), pero más conservador que el grupo anterior.

La solución de 4 conglomerados nos permite caracterizar los siguientes grupos. En primer lugar, se pueden destacar los grupos 2 y 4, que resultan perfiles opuestos entre si. El grupo 4 se puede definir como de “izquierda clásica” (prom=2.9 en escala de izquierda a derecha), con una fuerte propensión a la regulación estatal (prom=8.7) y posiciones valóricas liberales (prom=7.8). Al contrario, el grupo 2 representa una “centro-derecha clásica” (prom=5.5 en escala izquierda a derecha), más proclive al libre-mercado (prom=4.0) y posiciones conservadoras (prom=3.5).

Por otro lado, tenemos el primer y tercer conglomerado. El primer conglomerado puede denominarse de “centro-izquierda pragmática”, caracterizada por un promedio de 4.7 en la escala izquierda – derecha, con una posición más pro-mercado (prom=2.2) y liberal (prom=8.1). El tercer conglomerado corresponde a su grupo opuesto, que podríamos denominar de “derecha pragmática/social”, caracterizado por ser el grupo más a la derecha (prom=8.7), pero liberal (prom=7.0) y más proclive a la regulación del Estado.