Análisis factorial y mapas perceptuales

Introducción

El siguiente trabajo pretende identificar las estructura subyacente a partir de los datos provistos por una encuesta de opinión sobre la valoración de los usuarios hacia una empresa deportiva Shoetas, en este caso. sobre un producto de calzado ofertado por la misma.

A partir de este relevamiento, se busca ver si la estructura resultante del análisis tiene coincidencia con las dos dimensiones que la empresa tiene en cuenta para medir la valoración de los usuarios. Para esto, entonces, se entrevistan 189 usuarios en una tienda de artículos deportivos, que contestaron un cuestionario dividido en dos grandes apartados, lealtad cognitiva y lealtad afectiva, que consta de una escala valorativa de tipo Likert con 5 tipos de respuestas desde 1, como Completamente en desacuerdo, hasta 5, Completamente de acuerdo.

En cuanto al set de variables, las mismas se listan en la siguiente tabla.

Código
library(ggplot2)
library(tidyverse)
library(dplyr)
library(readxl)
library(haven)
library(knitr)
library(kableExtra)
library(VIM)
library(naniar)
library(corrplot)
library(gplots)
library(RColorBrewer)
library(psych)
library(semPlot)

encuesta = read_excel("Loyalty.xlsx")


tabla_lealtad = data.frame(
  Variable = c("CLOY1", "CLOY2", "CLOY3", "CLOY4", "CLOY5", "CLOY6",
               "ALOY1", "ALOY2", "ALOY3"),
  Significado = c("Es preferible usar zapatillas Shoetas",
    "Las características de las zapatillas Shoetas en general corresponden a mis expectativas",
    "Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su diseño",
    "Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su durabilidad",
    "Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su calidad",
    "Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su precio",
    "Me gustan más las zapatillas Shoetas que otras zapatillas",
    "Me gustan las características de mis zapatillas Shoetas",
    "Tengo una actitud positiva hacia las zapatillas Shoetas"),
  Dimension = c(rep("Cognitiva", 6), rep("Afectiva", 3)),
  stringsAsFactors = FALSE) |> select(3,1,2)

kbl(tabla_lealtad, align = "c") |>  
  kable_styling(full_width = FALSE, position = "c", font_size = 9) |>  
  column_spec(1:2, width = "3cm") |>   
  column_spec(3, width = "6cm") |>
  row_spec(0, bold = T, background = "#87CEEB") |>
  add_header_above(c("Tabla 1 - Variables de la encuesta"=3), font_size = 12, align = "l") |>
 collapse_rows(columns = 1, valign = "middle")
Tabla 1 - Variables de la encuesta
Dimension Variable Significado
Cognitiva CLOY1 Es preferible usar zapatillas Shoetas
CLOY2 Las características de las zapatillas Shoetas en general corresponden a mis expectativas
CLOY3 Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su diseño
CLOY4 Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su durabilidad
CLOY5 Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su calidad
CLOY6 Si alguien me propone usar otra marca de zapatillas, seguiré usando Shoetas por su precio
Afectiva ALOY1 Me gustan más las zapatillas Shoetas que otras zapatillas
ALOY2 Me gustan las características de mis zapatillas Shoetas
ALOY3 Tengo una actitud positiva hacia las zapatillas Shoetas

En primer lugar identificamos si nuestra encuesta tiene valores faltantes, y observamos las primeras y últimas 6 respuestas.

Código
## Primeras 6 respuestas

head(encuesta)
# A tibble: 6 × 10
  ALOY1 ALOY2 ALOY3 CLOY1 CLOY2 CLOY3 CLOY4 CLOY5 CLOY6    id
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     5     5     5     5     5     5     5     5     5     1
2     4     5     3     5     5     5     4     4     4     2
3     3     4     3     4     4     4     4     4     3     3
4     4     4     4     4     4     4     4     4     4     4
5     3     3     3     2     3     2     2     2     3     5
6     3     3     3     3     3     3     3     3     3     6
Código
# Últimas 6 respuestas

tail(encuesta)
# A tibble: 6 × 10
  ALOY1 ALOY2 ALOY3 CLOY1 CLOY2 CLOY3 CLOY4 CLOY5 CLOY6    id
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     4     5     5     4     4     4     4     4     5   184
2     4     3     3     4     4     4     3     5     3   185
3     5     5     4     4     4     5     5     5     4   186
4     5     5     4     5     5     5     5     5     5   187
5     5     5     4     5     4     5     5     5     5   188
6     5     5     4     5     5     5     5     5     5   189
Código
# Indago si hay missing


summary(encuesta)
     ALOY1           ALOY2          ALOY3           CLOY1           CLOY2      
 Min.   :1.000   Min.   :1.00   Min.   :1.000   Min.   :2.000   Min.   :1.000  
 1st Qu.:4.000   1st Qu.:4.00   1st Qu.:3.000   1st Qu.:4.000   1st Qu.:4.000  
 Median :4.000   Median :4.00   Median :4.000   Median :4.000   Median :4.000  
 Mean   :4.148   Mean   :4.28   Mean   :3.783   Mean   :4.275   Mean   :4.095  
 3rd Qu.:5.000   3rd Qu.:5.00   3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:5.000  
 Max.   :5.000   Max.   :5.00   Max.   :5.000   Max.   :5.000   Max.   :5.000  
     CLOY3           CLOY4           CLOY5           CLOY6             id     
 Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :  1  
 1st Qu.:4.000   1st Qu.:4.000   1st Qu.:4.000   1st Qu.:3.000   1st Qu.: 48  
 Median :4.000   Median :4.000   Median :4.000   Median :4.000   Median : 95  
 Mean   :4.175   Mean   :4.074   Mean   :4.169   Mean   :4.058   Mean   : 95  
 3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:5.000   3rd Qu.:142  
 Max.   :5.000   Max.   :5.000   Max.   :5.000   Max.   :5.000   Max.   :189  

Estandarización de los datos

Al no contar con datos faltantes, procedemos a estandarizar nuestros valores previo al armado de la matriz de correlaciones. De tal forma se evita introducir sesgos que puedan ser introducidos por distintos niveles de escalas de las variables tendiendo a afectar en un primer momento a la matriz, y luego por ende la conformación de los factores.

SI bien en este caso, la escala es la misma, se sugiere asignar media 0 y varianza 1 en caso de asimetría considerable en diversas variables.

Código
encuesta[,1:9] = data.frame(scale(encuesta[,1:9]))

## Selecciono variables de interés

encuesta = encuesta |> select(1:9)

Matriz de correlaciones

Generamos la matriz de correlaciones, y de antemano observamos correlación positiva fuerte entre las variables correspondientes a la dimensión cognitiva, y lo mismo entre las variables de la dimensión afectiva. Hasta aquí, según este esquema, parecería haber coincidencia con las dimensiones planteadas por la empresa.

Código
matriz = cor(encuesta)


corrplot(matriz, order="hclust")

Test de Barlett y Kaiser Meyer Olkin

Una vez culminado el armado de la matriz, procedemos a realizar un test que nos indique si es propicio realizar un análisis factorial. Tenemos dos formas para realizar este paso. Una de ellas, el Test de Barlett que corrobora si la matriz de correlación es una matriz de identidad -H0-, o si no lo es y son significativamente distintas -H1-

Esta prueba es muy similar a la prueba Chi Cuadrado, es donde, a valores pequeños del estadístico, existe una homogeneidad en las varianzas y por lo consiguiente existen un buen número de correlaciones positivas entre las variables.

Debe tenerse en cuenta que es muy sensible a la modificación del tamaño muestral.

Código
cortest.bartlett(matriz, n=189)
$chisq
[1] 1458.09

$p.value
[1] 3.203898e-283

$df
[1] 36

Por otro lado y una vez realizado el test anterior, calculamos la medida de adecuación de la muestra MSA o KMO (Kaiser-Meyer-Olkin). Este contrasta si las correlaciones parciales entre las variables son suficientemente pequeñas. El estadístico KMO varía entre 0 y 1. Los valores pequeños indican que el análisis factorial puede no ser una buena idea, dado que las correlaciones entre los pares de variables no pueden ser explicadas por otras variables. Los menores que 0.5 indican que no debe utilizarse el AF con la matriz de datos que se están analizando.

Código
KMO(matriz)
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = matriz)
Overall MSA =  0.86
MSA for each item = 
ALOY1 ALOY2 ALOY3 CLOY1 CLOY2 CLOY3 CLOY4 CLOY5 CLOY6 
 0.85  0.82  0.86  0.92  0.88  0.85  0.89  0.86  0.86 

Análisis factorial y Análisis de componentes principales

Probamos distintas técnicas para reducir dimensionalidad. La diferencia entre ambas depende del objetivo que se vaya a encarar. Si se busca resumir las dimensiones, es decir si se asume que existe una estructura subyacente que determina un fenómeno particular en los datos, y se busca dar cuenta de la existencia de la misma, como en este caso, se procede con el análisis factorial. Mientras que cuando se busca reducir dimensiones, por ejemplo para generar nuevos predictores para otro tipo de anális, por ejemplo, dificultado en un primer momento por problema de multicolinealidad, entonces corresponde un Análisis de Componentes Principales.

Procedemos en un primer momento, con el PCA, sin especificar rotación y cantidad de factores a extraer

Código
pca = prcomp(encuesta)

summary(pca)
Importance of components:
                          PC1    PC2     PC3     PC4     PC5     PC6     PC7
Standard deviation     2.3473 1.2743 0.69432 0.66346 0.53794 0.45382 0.42465
Proportion of Variance 0.6122 0.1804 0.05357 0.04891 0.03215 0.02288 0.02004
Cumulative Proportion  0.6122 0.7926 0.84619 0.89510 0.92725 0.95013 0.97017
                           PC8     PC9
Standard deviation     0.38314 0.34880
Proportion of Variance 0.01631 0.01352
Cumulative Proportion  0.98648 1.00000

Ahora, con un gráfico de sedimentación que toma el criterio de los autovalores mayores a 1, vemos la cantidad de factores a extraer, y veremos que solo 2 explican una cantidad de varianza superior a un atributo

Código
scree(matriz)

El PCA, como se exhibe, muestra cargas factoriales entre moderadas y bajas, lo que parece no ser ideal para identificar correlaciones entre atributos y componentes.

Código
pca2 = prcomp(encuesta, rank. = 2)
pca2
Standard deviations (1, .., p=9):
[1] 2.3473137 1.2742561 0.6943241 0.6634601 0.5379420 0.4538213 0.4246545
[8] 0.3831427 0.3487974

Rotation (n x k) = (9 x 2):
             PC1        PC2
ALOY1 -0.3301171 -0.3411057
ALOY2 -0.3340774 -0.3779836
ALOY3 -0.2926799 -0.4366218
CLOY1 -0.3297481  0.3077233
CLOY2 -0.3504813  0.2619504
CLOY3 -0.3416527  0.2582582
CLOY4 -0.3482747  0.3037055
CLOY5 -0.3422103  0.2970512
CLOY6 -0.3271891 -0.3736994

Probamos ahora con el análisis factorial, y vemos que las cargas factoriales presentan alta correlación con los factores.

En principio, parece haber coincidencia con los constructos latentes que determinarían el comportamiento de los clientes frente a la marca, sin embargo vemos que uno de los interrogantes relacionado inicialmente a la dimensión cognitiva presenta alta correlación a la dimensión afectiva. Lo vemos con el output de la cargas y un heatmap

Código
af = factanal(encuesta, factors=2)

af$loadings

Loadings:
      Factor1 Factor2
ALOY1 0.308   0.833  
ALOY2 0.278   0.893  
ALOY3 0.208   0.749  
CLOY1 0.801   0.205  
CLOY2 0.795   0.287  
CLOY3 0.767   0.290  
CLOY4 0.861   0.238  
CLOY5 0.836   0.243  
CLOY6 0.305   0.770  

               Factor1 Factor2
SS loadings      3.612   2.969
Proportion Var   0.401   0.330
Cumulative Var   0.401   0.731
Código
heatmap.2(af$loadings, 
          col=brewer.pal(9, "Greens"), trace="none", key=FALSE, dend="none",
          Colv=FALSE, cexCol = 1.2,
          main="\n\n\n\nHeatmap de cargas factoriales")

Visualizamos ahora la estructura, y vemos que CLOY6, es decir una variable anteriormente vinculada al componente racional sobre la elección del producto ante otras marcas por la variante precio, parece ahora quedar ligada al componente emocional.

Código
semPaths(af, what="est", residuals=FALSE,
         cut=0.7, posCol=c("white", "darkgreen"), negCol=c("white", "red"),
         edge.label.cex=0.75, nCharNodes=7)

Mapas perceptuales

En este apartado visualizamos la agrupación de los encuestados en torno a los factores generados según su puntuación factorial, donde a pesar de la alta densidad por la cantidad de puntos en el mapa, se pueden distinguir las dos dimensiones señaladas inicialmente, con la particularidad de la variable CLOY6 que se agrupa en torno al factor emocional.

Código
af_puntaje = factanal(encuesta, factors=2, 
                        scores="Bartlett")


biplot.psych(af_puntaje, main="Biplot",
             cex=c(1.5, 1),col=c(2,3,4),pch = c(21,18))

Rotación de ejes factoriales

La técnica de la rotación no tiene otra finalidad que mejorar/facilitar la interpretación de los factores extraídos de tal forma que coincida con el marco categorial que se esté manejando. Esto puede resultar útil cuando varios atributos se encuentran fuertemente correlacionados con más de un factor, con lo cual, y sin afectar la varianza total explicada, se debería lograr que haya una polarización entre cargas altas y bajas que evite la alta correlación de un atributo en múltiples factores.

Si bien no se aclaró anteriormente, la función factanal utiliza por deffault el método varimax de rotación que maximiza la varianza de las cargas al cuadrado de cada factor. Si hubieramos especificado que no se aplique ningún tipo de rotación, se observarían cargas altas alrededor del primer factor.

Además especificamos el metodo de extracción mle de máxima verosimilitud que requiere el supuesto de normalidad multivariada, a diferencia del método utilizado por default de residuos mínimos minres, que se utiliza en casos donde no se sabe que tipo de distribución adoptan las variables.

En nuestro ejemplo, al utilizar máxima verosimilitud, las cargas tiendes acrecentar la correlación con las factores aún más que con el método de residuos mínimos.

Código
rot = c("none", "varimax", "quartimax","Promax")

bi_mod = function(tipo){
biplot.psych(fa(encuesta[,c(1:9)], nfactors=2, rotate=tipo,fm="mle"),
             cex=c(1.5, 1),cuts=c(0),
             main = paste0("Biplot con rotación ",tipo),
             col=c(2,3,4),pch = c(21,18))
}

sapply(rot,bi_mod)

$none
NULL

$varimax
NULL

$quartimax
NULL

$Promax
NULL

Vemos que en lo que respecta a las rotaciones ortogonales (quartimax y varimax) la longitud de la flecha en el factor emocional indica que el atributo de mayor correlación es ALOY2, o sea, el gusto por las características de las zapatillas, mientras que el restante parece emparejar los valores de las cargas. Es en el mapa correspondiente a la rotación oblicua, donde el atributo de la durabilidad CLOY4 parece ser predominante aunque por una leve distancia.

En cuanto a los usuarios, su cercanía con una u otra dimensión se evalúa a partir de la puntuación factorial obtenida en los ejes que van de -3 a 3.

Conclusión

El análisis resultante nos llevó a enttender que efectivamente existen dos dimensiones distintas que determinan el comportamiento de los clientes, con la única salvedad que la elección del producto condicionada unicamente por la variabilidad del precio tiene mayor correlación con el factor emocional, lo que tal vez podría estar dando cuenta de un tipo de lealtad, la valoración positiva sobre las características, y la preferencia a toda costa de las zapatillas, mediada también por los precios.