You are here

Combining two single factor models into a two-factor model

1 post / 0 new
pehkawn's picture
Joined: 05/24/2020 - 19:45
Combining two single factor models into a two-factor model

Based on the two-factor model and joint ordinal-continuous model examples in the documentation, I tried creating two single-factor models (one continuous and one ordinal), which I tried to combine in a new model. In the new model essentially just tried to add a covariance path between the latent variables. This would useful when I want to expand existing models, without completely respecifying them, however I seem unable to combine them appropriately. First I got the prompt to add a joinKey, so I created a column with a unique entry for each row. Now I get the error:

"Error in mxPath(from = c("oneFactorContinuousModel.F1", "oneFactorOrdinalModel.F2"), : between level join mappings can only use single headed arrows"

Seemingly, OpenMx thinks I am trying to create a multilevel model, which I, in this case, am not. Is there a way I can add existing models in a new model, and expand upon them?

Here's my code example:

oneFactorJoint <- myFADataRaw[,c("x1","x2","x3","z1","z2","z3")] %>% mutate(key = 1:nrow(.))
oneFactorJoint$z1 <- mxFactor(oneFactorJoint$z1, levels=c(0,1))
oneFactorJoint$z2 <- mxFactor(oneFactorJoint$z2, levels=c(0,1))
oneFactorJoint$z3 <- mxFactor(oneFactorJoint$z3, levels=c(0,1,2))
dataRaw      <- mxData( observed=oneFactorJoint, type="raw", primaryKey = "key"  )
# Continuous factor model
# residual variances
resVarsX      <- mxPath( from=c("x1","x2","x3"), arrows=2,
                        free=c(TRUE, TRUE, TRUE),
                        values=1, labels=c("e1","e2","e3") )
# latent variance
latVarF1       <- mxPath( from=c("F1"), arrows=2, connect="unique.pairs",
                        free=TRUE, values=1, labels = c("varF1") )
# factor loadings
facLoadsX     <- mxPath( from="F1", to=c("x1","x2","x3"), arrows=1,
                        free=c(FALSE, TRUE, TRUE), values=1, labels=c("l1","l2","l3") )
# means
meansX        <- mxPath( from="one", to=c("x1","x2","x3","F1"), arrows=1,
                        free=c(TRUE,TRUE,TRUE,FALSE), values=0,
                        labels=c("meanx1","meanx2","meanx3","meanF1") )
oneFactorContinuousModel <- mxModel("Continuous Factor Model Path Specification", type="RAM",
                        manifestVars=c("x1","x2","x3"), latentVars=c("F1"),
                        dataRaw, resVarsX, latVarF1, facLoadsX, meansX)
oneFactorContinuousResults <- mxRun(oneFactorContinuousModel)
# Ordinal factor model
# residual variances
resVarsZ <- mxPath( from=c("z1","z2","z3"), arrows=2,
    free=c(FALSE, FALSE, FALSE),
    values=1, labels=c("e4","e5","e6") )
# latent variance
latVarZ <- mxPath( from=c("F2"), arrows=2, connect="unique.pairs",
    free=TRUE, values=1, labels = c("varF2") )
# factor loadings
facLoadsZ <- mxPath( from="F2", to=c("z1","z2","z3"), arrows=1,
    free=c(FALSE, TRUE, TRUE), values=1, labels=c("l4","l5","l6") )
# means
meansZ <- mxPath( from="one", to=c("z1","z2","z3","F2"), arrows=1,
    free=c(FALSE,FALSE,FALSE,FALSE), values=0,
    labels=c("meanz1","meanz2","meanz3","meanF2") )
# thresholds
thresholdsZ <- mxThreshold(vars=c("z1","z2","z3"), nThresh=c(1,1,2),
    free=TRUE, values=c(-1,0,-.5,1.2) )
oneFactorOrdinalModel <- mxModel("Ordinal Factor Model Path Specification", type="RAM",
    manifestVars=c("z1","z2","z3"), latentVars=c("F2"),
    dataRaw, resVarsZ, latVarZ, facLoadsZ, meansZ, thresholdsZ)
oneFactorOrdinalResults <- mxTryHardOrdinal(oneFactorOrdinalModel) %>% suppressMessages()
# Combine the two single-factor models combined into a two-factor model
# latent covariance
latCovar <- mxPath( from=c("oneFactorContinuousModel.F1", "oneFactorOrdinalModel.F2"), arrows=2, connect="unique.bivariate",
    free=TRUE, values=1, labels = c("cov"), joinKey = "key" )
twoFactorJointModel1 <- mxModel("Two-Factor Model Path Specification", type="RAM",
    oneFactorContinuousModel, oneFactorOrdinalModel,
    dataRaw, latCovar)