Understanding runHelper() error: MxExpectationRAM: latent exogenous variables are not supported
Attachment | Size |
---|---|
ex9.23.dat | 761.72 KB |
Error in runHelper(model, frontendStart, intervals, silent, suppressWarnings, :
MxExpectationRAM: latent exogenous variables are not supported (x -> sw)
Even without any other changes to the code, I get this error. I've fitted models with WLS before without issue, but I fail to identify what may differs that would cause this error. Furthermore, I am trying to understand why I get this error using WLS, but not with ML.
Code sample:
# MPlus: Three-level growth model with a continuous outcome and one covariate on each of the three levels
# https://www.statmodel.com/usersguide/chapter9.shtml
library(OpenMx)
#mxOption(NULL, "Number of Threads", 8L)
options(width=120)
ex923 <- suppressWarnings(try(read.table("ex9.23.dat")))
# if (is(ex923, "try-error")) ex923 <- read.table("data/ex9.23.dat")
colnames(ex923) <- c(paste0('y',1:4), 'x', 'w', 'z', 'level2', 'level3')
ex923$level2 <- as.integer(ex923$level2)
ex923$level3 <- as.integer(ex923$level3)
level3Model <- mxModel(
'level3Model', type='RAM',
latentVars=c(paste0('y',1:4), 'ib3', 'sb3', 'z'),
mxData(ex923[!duplicated(ex923$level3),], 'raw', primaryKey='level3'),
mxPath('ib3', paste0('y',1:4), free=FALSE, values=1),
mxPath('sb3', paste0('y',1:4), free=FALSE, values=0:3),
mxPath(c('ib3','sb3'), arrows=2, connect="unique.pairs", values=c(1,0,1)),
mxPath('one', 'z', free=FALSE, labels="data.z"),
mxPath('z', c('ib3','sb3')),
mxPath('one', c('ib3','sb3')))
level2Model <- mxModel(
'level2Model', type='RAM', level3Model,
latentVars=c(paste0('y',1:4), 'ib2', 'sb2', 'w'),
mxData(ex923[!duplicated(ex923$level2),], 'raw', primaryKey='level2'),
mxPath('ib2', paste0('y',1:4), free=FALSE, values=1),
mxPath('sb2', paste0('y',1:4), free=FALSE, values=0:3),
mxPath(c('ib2','sb2'), arrows=2, connect="unique.pairs", values=c(1,0,1)),
mxPath('one', 'w', free=FALSE, labels="data.w"),
mxPath('w', c('ib2','sb2')),
mxPath(paste0('y',1:4), arrows=2),
mxPath(paste0('level3Model.y', 1:4), paste0('y',1:4), free=FALSE, values=1,
joinKey="level3"))
withinModel <- NULL
withinModel <- mxModel(
'withinModel',
type='RAM',
level2Model,
manifestVars=c(paste0('y',1:4)),
latentVars=c('iw','sw', 'x'),
mxData(ex923, 'raw'),
mxPath('iw', paste0('y',1:4), free=FALSE, values=1),
mxPath('sw', paste0('y',1:4), free=FALSE, values=0:3),
mxPath(paste0('y',1:4), arrows=2),
mxPath(c('iw','sw'), arrows=2, connect="unique.pairs", values=c(1,0,1)),
mxPath('one', 'x', free=FALSE, labels="data.x"),
mxPath('x', c('iw','sw')),
mxPath(paste0('level2Model.y', 1:4), paste0('y',1:4), free=FALSE, values=1,
joinKey="level2"),
mxFitFunctionWLS() # Added alternative fit function
)
withinModel <- mxRun(withinModel)
omxCheckEquals(withinModel$expectation$debug$rampartUsage, c(6000))
omxCheckCloseEnough(logLik(withinModel), -56044.82, 1e-2) # matches Mplus
No WLS with Multilevel
Log in or register to post comments
In reply to No WLS with Multilevel by mhunter
I'm confused
Log in or register to post comments
Why WLS?
Is there a particular reason you want to run this model or a similar model with WLS?
Log in or register to post comments
In reply to Why WLS? by mhunter
The reason I've been trying to to use WLS
Now, it's the first time I've seen the error message I posted above. Actually, OpenMx does not really produce any error messages when fitting a multilevel model with WLS, which is problematic if this is not possible. Below I've modified the example above to one that will not produce the aforementioned error message. (For the sake of demonstration, I've added an ordinal variable on level 1 and latent interactions on all levels.) It does not produce any estimates or standard errors for upper levels, however, which sort of makes sense now. There really should be a warning/error message prohibiting fitting multilevel models using WLS. As for fitting multilevel models, there's a real need to implement ways to model ordinal/categorical/dichotomous variables in such models.
## ---------------------------------------------------------------------------------------------------------------------
Sys.setenv(OMP_NUM_THREADS=parallel::detectCores())
library(OpenMx)
library(dplyr)
library(magrittr)
#mxOption(NULL, "Number of Threads", 8L)
options(width=120)
## ---------------------------------------------------------------------------------------------------------------------
ex923 <- suppressWarnings(try(read.table("ex9.23.dat")))
colnames(ex923) <- c(paste0('y',1:4), 'x', 'w', 'z', 'level2', 'level3')
ex923 %<>%
mutate(across( x:z, ~ { round(. - min(.) + 1) } ) )
ex923$x %<>% as.ordered()
## ---------------------------------------------------------------------------------------------------------------------
# Level 3 model
level3Model <- mxModel(
# Model name
'level3Model',
# Model type
type = 'RAM',
# Variables. Manifest, latent and product variables, respectively.
manifestVars = 'z',
latentVars=c(paste0('y',1:4), 'ib3', 'sb3'),
productVars=c("ib3×sb3"),
# residual manifest variances
mxPath(
from = 'z',
arrows = 2,
free = FALSE,
values = 1
),
# latent variances & covariances
mxPath(
from = paste0('y',3:4),
connect = "unique.bivariate",
arrows = 2,
free = TRUE,
values = 0.1,
labels = "cov_y3_y4"
),
mxPath(
from = c('ib3','sb3'),
connect = "unique.pairs",
arrows = 2,
free = TRUE,
values = 0.4,
labels = c("e_ib3", "cov_ib3_sb3", "e_sb3")
),
# pattern coefficients
mxPath(
from = "ib3",
to = paste0('y',1:2),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('ib3_y',1:2)
),
mxPath(
from = "sb3",
to = paste0('y',3:4),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('sb3_y', 3:4)
),
mxPath(
from = c("ib3", "sb3"),
to = "z",
arrows = 1,
free = TRUE,
values = 1,
lbound = 1e-6,
labels = paste0(c("ib3", "sb3"), "_z")
),
# Latent interactions
mxPath(
from = c("ib3","sb3"),
to = "ib3×sb3",
arrows = 1,
free = FALSE,
values = 1
),
mxPath(
from = "ib3×sb3",
to = "z",
arrows = 1,
free = TRUE,
values = .5,
labels = "ib3×sb3_z"
),
# means
means = mxPath(
from = "one",
to = c(paste0('y',1:4), 'z', 'ib3', 'sb3'),
arrows = 1,
free = TRUE,
values = 0,
labels = paste0("μ_", c(paste0('y',1:4), 'z', 'ib3', 'sb3'))
),
# # thresholds
# mxThreshold(
# vars = "z",
# nThresh = max(as.double(ex923$z)) - 1,
# free = TRUE,
# values = mxNormalQuantiles(max(as.double(ex923$z)) - 1),
# labels = paste0("z_thresh_", 1:(max(as.double(ex923$z)) - 1)),
# ),
mxData(ex923[!duplicated(ex923$level3),], 'raw', primaryKey='level3')
)
# Level 2 model
level2Model <- mxModel(
# Model name
'level2Model',
# Model type
type = 'RAM',
# Higher level model to insert
level3Model,
# Variables. Manifest, latent and product variables, respectively.
manifestVars = 'w',
latentVars=c(paste0('y',1:4), 'ib2', 'sb2'),
productVars=c("ib2×sb2"),
# residual manifest variances
mxPath(
from = 'w',
arrows = 2,
free = FALSE,
values = 1
),
# latent variance & covariance
mxPath(
from = paste0('y',3:4),
connect = "unique.bivariate",
arrows = 2,
free = TRUE,
values = 0.1,
labels = "cov_y3_y4"
),
mxPath(
from = c('ib2','sb2'),
connect = "unique.pairs",
arrows = 2,
free = TRUE,
values = 0.4,
labels = c("e_ib2", "cov_ib2_sb2", "e_sb2")
),
# pattern coefficients
mxPath(
from = "ib2",
to = paste0('y',1:2),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('ib2_y',1:2)
),
mxPath(
from = "sb2",
to = paste0('y',3:4),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('sb2_y', 3:4)
),
mxPath(
from = c("ib2", "sb2"),
to = "w",
arrows = 1,
free = TRUE,
values = 1,
lbound = 1e-6,
labels = paste0(c("ib2", "sb2"), "_w")
),
# Latent interactions
mxPath(
from = c("ib2","sb2"),
to = "ib2×sb2",
arrows = 1,
free = FALSE,
values = 1
),
mxPath(
from = "ib2×sb2",
to = "w",
arrows = 1,
free = TRUE,
values = .5,
labels = "ib2×sb2_w"
),
# means
means = mxPath(
from = "one",
to = c(paste0('y',1:4), 'w', 'ib2', 'sb2'),
arrows = 1,
free = TRUE,
values = 0,
labels = paste0("μ_", c(paste0('y',1:4), 'w', 'ib2', 'sb2'))
),
# # thresholds
# mxThreshold(
# vars = "w",
# nThresh = max(as.double(ex923$w)) - 1,
# free = TRUE,
# values = mxNormalQuantiles(max(as.double(ex923$w)) - 1),
# labels = paste0("w_thresh_", 1:(max(as.double(ex923$w)) - 1)),
# ),
# Cross-level
mxPath(
from = paste0('level3Model.y', 1:4),
to = paste0('y',1:4),
free = FALSE,
values = 1,
joinKey = "level3"
),
# Data
mxData(ex923[!duplicated(ex923$level2),], 'raw', primaryKey='level2')
)
# Level 1 model. (Full model.)
withinModel <- mxModel(
# Model name
'withinModel',
# Model type
type='RAM',
# Higher level model to insert
level2Model,
# Variables. Manifest, latent and product variables, respectively.
manifestVars=c(paste0('y',1:4), 'x'),
latentVars=c('iw','sw'),
productVars=c("iw×sw"),
# residual variances
mxPath(
from = c(paste0('y',1:4), 'x'),
arrows = 2,
free = FALSE,
values = 1
),
# residual covariances
mxPath(
from = paste0('y',1:2),
connect = "unique.bivariate",
arrows = 2,
free = TRUE,
values = 0.1,
labels = "cov_y1_y2"
),
mxPath(
from = paste0('y',3:4),
connect = "unique.bivariate",
arrows = 2,
free = TRUE,
values = 0.1,
labels = "cov_y3_y4"
),
# latent variance & covariance
mxPath(
from = c('iw','sw'),
connect = "unique.pairs",
arrows = 2,
free = TRUE,
values = 0.4,
labels = c("e_iw", "cov_iw_sw", "e_sw")
),
# pattern coefficients
mxPath(
from = "iw",
to = paste0('y',1:2),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('iw_y',1:2)
),
mxPath(
from = "sw",
to = paste0('y',3:4),
arrows = 1,
free = c(FALSE, TRUE),
values = 1,
lbound = 1e-6,
labels = paste0('sw_y', 3:4)
),
mxPath(
from = c("iw", "sw"),
to = "x",
arrows = 1,
free = TRUE,
values = 1,
lbound = 1e-6,
labels = paste0(c("iw", "sw"), "_x")
),
# Latent interactions
mxPath(
from = c("iw","sw"),
to = "iw×sw",
arrows = 1,
free = FALSE,
values = 1
),
mxPath(
from = "iw×sw",
to = "x",
arrows = 1,
free = TRUE,
values = .5,
labels = "iw×sw_x"
),
# means
means = mxPath(
from = "one",
to = c(paste0('y',1:4), 'x', 'iw', 'sw'),
arrows = 1,
free = TRUE,
values = 0,
labels = paste0("μ_", c(paste0('y',1:4), 'x', 'iw', 'sw'))
),
# thresholds
mxThreshold(
vars = "x",
nThresh = max(as.double(ex923$x)) - 1,
free = TRUE,
values = mxNormalQuantiles(max(as.double(ex923$x)) - 1),
labels = paste0("x_thresh_", 1:(max(as.double(ex923$x)) - 1)),
),
# Cross-level
mxPath(
from = paste0('level2Model.y', 1:4),
to = paste0('y',1:4),
free = FALSE,
values = 1, joinKey = "level2"
),
# Data
mxData(ex923, 'raw'),
# Fit function: WLS
mxFitFunctionWLS(
# allContinuousMethod = 'marginals'
)
)
## ---------------------------------------------------------------------------------------------------------------------
withinModel %>%
mxRun() %>%
summary()
Log in or register to post comments
In reply to The reason I've been trying to to use WLS by pehkawn
Go Bayes or go home
OpenMx is not the right tool for the job, though. I am not aware of any *non-Bayesian* general method for fitting multilevel models to such variables. Look into stan.
Agreed.
Log in or register to post comments
Now throw error
Log in or register to post comments
In reply to Now throw error by mhunter
next release
Or, at least it will in its next stable-version release.
Log in or register to post comments