The purpose of this factor analysis example is to detect the underlying structure in the relationship between several loyalty items measured in a survey. The dataset used within this section is called Loyalty.xls and it describes the following managerial problem.
The sports company Shoetas wishes to assess the degree of consumers´loyalty towards Shoetas´trainers. They interviewed 189 consumers in a sports store through the medium of a questionnaire. Two dimensions of loyalty are taken into consideration, namely the cognitive loyalty and the affective loyalty. Cognitive loyalty was measured by rating six statements on 5-point Likert-scale, ranging from 1 = “completely disagree” to 5 = “completely agree”. The statements used in the questionnaire are the following:
Affective loyalty was measured by rating three statements on 5-point Likert-scale, ranging from 1 = completely disagree to 5= completely agree. The statements used in the questionnaire are the the following:
El problema planteado por la compañía Shoetas implica una solución mediante un análisis que permita entender si las evaluaciones de la marca se corresponden efectivamente con la estructura de las variables latentes construídas por la empresa. Para ello se buscará definir mediante un análisis de factores si las estructuras predefinidas de las dimensiones de “Cognitive Loyalty” y de “Affective Loyalty” se corresponden con el set de variables utilizados. Se trabajará con la base loyalty que incluye las 9 variable de las dimensiones cognitivas y afectivas y cuenta con 189 observaciones.
#Levantamos el archivo
library(readxl)
loyalty<- read_excel(path ="C:\\Users\\jonat\\OneDrive\\Escritorio\\Maestria generacion y analisis de informacion estadistica\\9. Estadistica aplicada a la investigacion de mercados\\2. Mapas perceptuales\\Loyalty.xls")
library(tidyverse)
loyalty<- column_to_rownames(loyalty, var= "id")
El primer paso antes de realizar un análisis de corrrespondencia es identificar si nuetra base cuenta con casos perdidos que requieran ser reemplazados.
#Chequeamos la estructura de la base
summary(loyalty)
## 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
## Min. :1.000 Min. :1.000 Min. :1.000 Min. :1.000
## 1st Qu.:4.000 1st Qu.:4.000 1st Qu.:4.000 1st Qu.:3.000
## Median :4.000 Median :4.000 Median :4.000 Median :4.000
## Mean :4.175 Mean :4.074 Mean :4.169 Mean :4.058
## 3rd Qu.:5.000 3rd Qu.:5.000 3rd Qu.:5.000 3rd Qu.:5.000
## Max. :5.000 Max. :5.000 Max. :5.000 Max. :5.000
str(loyalty)
## 'data.frame': 189 obs. of 9 variables:
## $ ALOY1: num 5 4 3 4 3 3 3 3 5 5 ...
## $ ALOY2: num 5 5 4 4 3 3 4 3 5 5 ...
## $ ALOY3: num 5 3 3 4 3 3 3 3 3 5 ...
## $ CLOY1: num 5 5 4 4 2 3 5 4 4 5 ...
## $ CLOY2: num 5 5 4 4 3 3 5 4 4 5 ...
## $ CLOY3: num 5 5 4 4 2 3 5 4 5 5 ...
## $ CLOY4: num 5 4 4 4 2 3 5 4 5 5 ...
## $ CLOY5: num 5 4 4 4 2 3 5 4 5 5 ...
## $ CLOY6: num 5 4 3 4 3 3 4 3 3 5 ...
Una vez que nos aseguramos que nuestra base no cuenta con casos perdidos, procedemos a estandarizar todas las variables. Este proceso evita sesgos que puedan ser introducidos por distintos niveles de escalas de las variables y que puedan afectar al análisis factorial. De este modo se asumen todas las variables con media “0” (cero).
#Standarizamos las escalas de las variables a factorizar
loyalty_scale<- data.frame(scale(loyalty))
summary(loyalty_scale)
## ALOY1 ALOY2 ALOY3 CLOY1
## Min. :-3.7310 Min. :-4.0370 Min. :-3.0941 Min. :-3.1561
## 1st Qu.:-0.1756 1st Qu.:-0.3451 1st Qu.:-0.8706 1st Qu.:-0.3817
## Median :-0.1756 Median :-0.3451 Median : 0.2412 Median :-0.3817
## Mean : 0.0000 Mean : 0.0000 Mean : 0.0000 Mean : 0.0000
## 3rd Qu.: 1.0096 3rd Qu.: 0.8855 3rd Qu.: 1.3529 3rd Qu.: 1.0056
## Max. : 1.0096 Max. : 0.8855 Max. : 1.3529 Max. : 1.0056
## CLOY2 CLOY3 CLOY4 CLOY5
## Min. :-3.9022 Min. :-4.0201 Min. :-3.71160 Min. :-3.8624
## 1st Qu.:-0.1201 1st Qu.:-0.2211 1st Qu.:-0.08944 1st Qu.:-0.2063
## Median :-0.1201 Median :-0.2211 Median :-0.08944 Median :-0.2063
## Mean : 0.0000 Mean : 0.0000 Mean : 0.00000 Mean : 0.0000
## 3rd Qu.: 1.1406 3rd Qu.: 1.0452 3rd Qu.: 1.11795 3rd Qu.: 1.0124
## Max. : 1.1406 Max. : 1.0452 Max. : 1.11795 Max. : 1.0124
## CLOY6
## Min. :-3.64474
## 1st Qu.:-1.26116
## Median :-0.06936
## Mean : 0.00000
## 3rd Qu.: 1.12243
## Max. : 1.12243
La primera aproximación para entender si nuestras variables son factorizables es realizar una matriz de correlación la cual nos arroja un primer indicio sobre si podremos hallar algún tipo de relación entre las variables que nos den cuenta de variables latentes o no observadas. Viendo la matriz de correlación se pueden identificar varias variables con buenas correlaciones con un coeficiente del 0.4 o más. Por ejemplo, CLOY1 correlaciona fuertemente con otras variables de la dimensión denominada lealtad cognitiva pero lo hace en menor medida con las variables de la dimensión afectiva.
#Observamos las correlaciones entre las variables
library(corrplot)
correla_loyalty <- cor(loyalty_scale)
#Observamos las correlaciones entre las variables
corrplot(correla_loyalty, order= "hclust")
Siguiendo lo expusto más arriba, el Test de Bartlett nos indica de manera numérica si la correlación entre las variables analizadas es lo suficientemente grande para realizar un análisis. Este test parte de la Hipótesis nula de que la matriz de coeficientes de correlación no es significativamente distinta de la matriz de identidad. En nuestro caso con un P value de 3.203898e-283 rechazamos la hipótesis nula y podemos decir que la correlación es significativamente distinta de la matriz de identidad.
#Testeo de esfericidad
library(psych)
cortest.bartlett(correla_loyalty, n=189)
## $chisq
## [1] 1458.09
##
## $p.value
## [1] 3.203898e-283
##
## $df
## [1] 36
Además de contrastar si las correlaciones son distintas a la matriz de identidad, debemos contrastar si la muestra es lo suficientemente pequeña para un análisis factorial. El test de Kaiser-Meyer-Olkin tiene como finalidad determinar qué tan adecuada es nuestra muestra. Con un Overall MSA = 0.86 nuestra muestra presenta una buena adecuación para un análisis factorial, también se observan buenos valores para cada una de las variables.
#Test de KMO
KMO(loyalty_scale)
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = loyalty_scale)
## 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
Una vez que nos hemos asegurado que nuestro set de datos sea válido para un análisis factorial o un análisis de componentes principales podemos proceder. A continuación se corre un análisis de componentes principales en el cual podemos destacar que siguiendo el método de los autovalores, podríamos decir que se identifican dos componentes principales. Tanto el PC1 y el PC2 tienen valores de desvío standard mayor a uno lo cuál nos da un indicio de que estos son los dos componentes a seleccionar y que entre los dos explican casi el 80% de la variancia total.
#Componentes principales
loyalty_PC<- prcomp(loyalty_scale)
summary(loyalty_PC)
## 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
En cambio, en el criterio del constrante de caída, se observa que la curva tiende a estancarse a partir del tercer componente. Sin embargo, si tomamos el criterio de la raíz latente se observa que el componente PC3 tiene un valor bajo de sólo un 0.5% de la variancia.
#Ploteamos el grafico de sedimentacion
plot(loyalty_PC, type= 'l')
En el análisis del biplot podemos ver que las variables se agrupan en dós grupos homogéneos entre sí mientras que no se distingue una fuerte tendencia a la dispersión de los casos sino que tienen a concentrarse de manera homogénea.
#Biplot
biplot(loyalty_PC)
Entonces, si quisieramos determinar la cantidad de componentes para un análisis de los componentes principales deberíamos delimitarnos a dos grupos. En este punto sólo bastaría contrastar las cargas de las variables para determinar si la estructura de las dimensiones afectivas y cognitivas de lealtad a Shoetas se cumple o no. Las cargas de las variables para el componente uno son negatiivas y no presentarían de manera clara alguna tendencia en particular, mientras que el componente dos tiene signos positivos en todas las variables de lealtad afectiva (ALOY1 a ALOY3) y CLOY (6). El análisis de los componentes principales nos permitiría reducir los datos e incluso crear escalas aditivas. Pero como nuestro fin es determinar la estructura, resultará pertinente proceder con un análisis factorial.
#Seleccionamos los factores mediante el metodo de los componentes principales. Solo 2 sin rotacion
loyalty_PC<- prcomp(loyalty_scale, rank. = 2)
loyalty_PC
## 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
Los eigenvalues del análisis factorial nos permite deducir una conclusión similar a la de los componentes principales en lo referido a la cantidad de factores que vamos a seleccionar. A continuación se muestran los eingenvalues, la forma gráfica de solución y el análisis de paralelas comparando el método de componentes principales y de análisis factorial con la información real y simulada. Queda claro entonces que la solución evidente es la de seleccionar dos componentes o factores.
#Eigenvalues para el FA
library(nFactors)
## Warning: package 'nFactors' was built under R version 4.1.3
## Loading required package: lattice
##
## Attaching package: 'nFactors'
## The following object is masked from 'package:lattice':
##
## parallel
eigen(correla_loyalty)
## eigen() decomposition
## $values
## [1] 5.5098814 1.6237286 0.4820859 0.4401793 0.2893816 0.2059538 0.1803314
## [8] 0.1467983 0.1216596
##
## $vectors
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] -0.3301171 -0.3411057 0.21583769 0.513355328 0.19219336 0.21788717
## [2,] -0.3340774 -0.3779836 0.04280657 0.417532801 0.06241108 -0.12104156
## [3,] -0.2926799 -0.4366218 -0.14587272 -0.510398767 -0.27681348 0.48858802
## [4,] -0.3297481 0.3077233 0.23827156 -0.322523659 0.74877438 0.08425939
## [5,] -0.3504813 0.2619504 -0.48336607 0.053667913 -0.03842030 0.32355544
## [6,] -0.3416527 0.2582582 -0.58471172 0.180573728 0.02338267 -0.22646331
## [7,] -0.3482747 0.3037055 0.26361597 0.004848457 -0.47859480 -0.34402261
## [8,] -0.3422103 0.2970512 0.47747882 -0.010904116 -0.29345544 0.23091770
## [9,] -0.3271891 -0.3736994 -0.02279367 -0.402460846 0.06845323 -0.60366210
## [,7] [,8] [,9]
## [1,] 0.1892345 0.364854324 0.45957427
## [2,] -0.1380196 -0.355396485 -0.63675144
## [3,] 0.3334972 -0.105311462 -0.06526315
## [4,] 0.1842492 -0.005753169 -0.18448331
## [5,] -0.4951535 0.437516093 -0.17105654
## [6,] 0.3379657 -0.422155399 0.31275077
## [7,] 0.3926143 0.385501627 -0.25843532
## [8,] -0.3851210 -0.443506929 0.28651716
## [9,] -0.3716327 0.120439381 0.26285252
#Scree para determinar factores del analisis factorial
scree(loyalty_scale)
#Analisis de las paralelas
fa.parallel(loyalty_scale, n.obs = 100)
## Parallel analysis suggests that the number of factors = 2 and the number of components = 2
Debido a que nuestra intención es entender los constructos que subyacen a los datos, realizamos un análisis factorial con dos factores.
#Fa para entender los constructos que subyacen a los datos con 2 factores
loyalty_fa<- factanal(loyalty_scale, factors= 2)
loyalty_fa$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
Al observar las cargas factoriales para estos dos factores es un poco más clara la solución con respecto a nuestro problema. La estructura de las dimensiones pareciera responder a las categorías creadas por Shoetas para medir la lealtad de los clientes hacia la marca, pero con algunas salvedades. Mientras que las variables de lealtad afectiva responden efectivamente a la dimensión, no todas las variables de lealtad cognitiva lo hacen bien con su dimensión. La variable CLOY6(“If someone proposes that I use another trainers’ brand, I will continue using Shoetas for their price”) responde de hecho a cuestiones más relacionadas con las variables emocionales que a cuestiones racionales. Podríamos decir que la elección de Shoetas por su precio sobre el precio de otras zapatillas está ligada a una dimensión de lealtad emocional más que racional o de producto en sí.
#Visualizamos la estructura de los dos factores obtenidos
library(gplots)
library(RColorBrewer)
heatmap.2(loyalty_fa$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 la estructura
library(semPlot)
semPaths(loyalty_fa, what="est", residuals=FALSE,
cut=0.7, posCol=c("white", "darkgreen"), negCol=c("white", "red"),
edge.label.cex=0.75, nCharNodes=7)