Supongo que el foco de la pregunta es menos en el lado teórico y más en el lado práctico, es decir, cómo implementar un análisis factorial de datos dicotómicos en R.
Primero, simulemos 200 observaciones de 6 variables, provenientes de 2 factores ortogonales. Tomaré un par de pasos intermedios y comenzaré con datos continuos normales multivariados que luego dicotomizaré. De esa manera, podemos comparar las correlaciones de Pearson con las correlaciones policóricas, y comparar las cargas de factores de datos continuos con las de datos dicotómicos y las cargas reales.
set.seed(1.234)
N <- 200 # number of observations
P <- 6 # number of variables
Q <- 2 # number of factors
# true P x Q loading matrix -> variable-factor correlations
Lambda <- matrix(c(0.7,-0.4, 0.8,0, -0.2,0.9, -0.3,0.4, 0.3,0.7, -0.8,0.1),
nrow=P, ncol=Q, byrow=TRUE)
x = Λ f+ eXΛFmi iid, media 0, errores normales.
library(mvtnorm) # for rmvnorm()
FF <- rmvnorm(N, mean=c(5, 15), sigma=diag(Q)) # factor scores (uncorrelated factors)
E <- rmvnorm(N, rep(0, P), diag(P)) # matrix with iid, mean 0, normal errors
X <- FF %*% t(Lambda) + E # matrix with variable values
Xdf <- data.frame(X) # data also as a data frame
Haga el análisis factorial para los datos continuos. Las cargas estimadas son similares a las verdaderas cuando se ignora el signo irrelevante.
> library(psych) # for fa(), fa.poly(), factor.plot(), fa.diagram(), fa.parallel.poly, vss()
> fa(X, nfactors=2, rotate="varimax")$loadings # factor analysis continuous data
Loadings:
MR2 MR1
[1,] -0.602 -0.125
[2,] -0.450 0.102
[3,] 0.341 0.386
[4,] 0.443 0.251
[5,] -0.156 0.985
[6,] 0.590
Ahora vamos a dicotomizar los datos. Mantendremos los datos en dos formatos: como un marco de datos con factores ordenados y como una matriz numérica. hetcor()
del paquetepolycor
nos da la matriz de correlación policórica que luego usaremos para la FA.
# dichotomize variables into a list of ordered factors
Xdi <- lapply(Xdf, function(x) cut(x, breaks=c(-Inf, median(x), Inf), ordered=TRUE))
Xdidf <- do.call("data.frame", Xdi) # combine list into a data frame
XdiNum <- data.matrix(Xdidf) # dichotomized data as a numeric matrix
library(polycor) # for hetcor()
pc <- hetcor(Xdidf, ML=TRUE) # polychoric corr matrix -> component correlations
Ahora use la matriz de correlación policórica para hacer un FA regular. Tenga en cuenta que las cargas estimadas son bastante similares a las de los datos continuos.
> faPC <- fa(r=pc$correlations, nfactors=2, n.obs=N, rotate="varimax")
> faPC$loadings
Loadings:
MR2 MR1
X1 -0.706 -0.150
X2 -0.278 0.167
X3 0.482 0.182
X4 0.598 0.226
X5 0.143 0.987
X6 0.571
Puede omitir el paso de calcular la matriz de correlación policórica usted mismo y usar directamente fa.poly()
desde el paquetepsych
, que al final hace lo mismo. Esta función acepta los datos dicotómicos en bruto como una matriz numérica.
faPCdirect <- fa.poly(XdiNum, nfactors=2, rotate="varimax") # polychoric FA
faPCdirect$fa$loadings # loadings are the same as above ...
EDITAR: Para puntajes de factores, mire el paquete ltm
que tiene unfactor.scores()
función específica para datos de resultados politómicos. Se proporciona un ejemplo en esta página -> "Puntajes de factor - Estimaciones de habilidad".
Puede visualizar las cargas del análisis factorial usando factor.plot()
y fa.diagram()
, tanto del paquete psych
. Por alguna razón, factor.plot()
acepta solo el $fa
componente del resultado de fa.poly()
, no el objeto completo.
factor.plot(faPCdirect$fa, cut=0.5)
fa.diagram(faPCdirect)
El análisis paralelo y un análisis de "estructura muy simple" proporcionan ayuda para seleccionar la cantidad de factores. Nuevamente, el paquete psych
tiene las funciones requeridas. vss()
toma la matriz de correlación policórica como argumento.
fa.parallel.poly(XdiNum) # parallel analysis for dichotomous data
vss(pc$correlations, n.obs=N, rotate="varimax") # very simple structure
El paquete también proporciona un análisis paralelo para la FA policlorica random.polychor.pa
.
library(random.polychor.pa) # for random.polychor.pa()
random.polychor.pa(data.matrix=XdiNum, nrep=5, q.eigen=0.99)
Tenga en cuenta que las funciones fa()
y fa.poly()
proporcionan muchas más opciones para configurar la FA. Además, edité algunos de los resultados que ofrecen pruebas de bondad de ajuste, etc. La documentación para estas funciones (y paquetepsych
en general) es excelente. Este ejemplo aquí solo tiene la intención de comenzar.