Supongo que el enfoque 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, vamos a simular 200 observaciones de 6 variables, procedentes de 2 factores ortogonales. Daré un par de pasos intermedios y empezaré con datos continuos normales multivariados que luego dicotomizaré. De esta manera, podemos comparar las correlaciones de Pearson con las correlaciones policóricas, y comparar las cargas de los factores de los datos continuos con las de los datos dicotómicos y las cargas verdaderas.
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)
Ahora simule los datos reales del modelo $x = \Lambda f + e$ con $x$ siendo los valores de las variables observadas de una persona, $\Lambda$ la verdadera matriz de cargas, $f$ la puntuación del factor latente, y $e$ 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
Realice 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 paquete polycor
nos da la matriz de correlación policórica que luego usaremos para el AF.
# 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 usa la matriz de correlación policórica para hacer un FA regular. Observe 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 utilizar directamente fa.poly()
del paquete psych
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 ...
EDIT: Para las puntuaciones de los factores, mira el paquete ltm
que tiene un factor.scores()
específicamente para datos de resultados politómicos. Se ofrece un ejemplo en esta página -> "Puntuaciones de los factores - Estimaciones de la capacidad".
Puede visualizar las cargas del análisis factorial utilizando factor.plot()
y fa.diagram()
, ambos del paquete psych
. Por alguna razón, factor.plot()
sólo acepta el $fa
del resultado de fa.poly()
, no el objeto completo.
factor.plot(faPCdirect$fa, cut=0.5)
fa.diagram(faPCdirect)
El análisis paralelo y el de "estructura muy simple" ayudan a seleccionar el número de factores. De nuevo, el paquete psych
tiene las funciones necesarias. vss()
toma como argumento la matriz de correlación policórica.
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 AF policórica 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, he editado parte de la salida que da pruebas de bondad de ajuste, etc. La documentación de estas funciones (y del paquete psych
en general) es excelente. Este ejemplo sólo sirve para empezar.