Combining two single factor models into a two-factor model

Posted on
Picture of user. pehkawn Joined: 05/24/2020
Based on the [two-factor model](https://vipbg.vcu.edu/vipbg/OpenMx2/docs//OpenMx/latest/FactorAnalysis_Path.html#two-factor-model ) and [joint ordinal-continuous model](https://vipbg.vcu.edu/vipbg/OpenMx2/docs//OpenMx/latest/Ordinal_Path.html#joint-ordinal-continuous-data) 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:

require(OpenMx)
require(dplyr)

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()

# [THIS IS WHERE I AM STUCK:]
# 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)