| umxRAM | R Documentation |
umxRAM expedites creation of structural equation models, still without doing invisible things to the model. It
supports umxPath(). To support cross-language sharing and science learning, umxRAM also supports lavaan model strings.
Here's a path example that models miles per gallon (mpg) as a function of weight (wt) and engine displacement (disp)
using the widely used mtcars data set.
m1 = umxRAM("tim", data = mtcars,
umxPath(c("wt", "disp"), to = "mpg"),
umxPath("wt", with = "disp"),
umxPath(v.m. = c("wt", "disp", "mpg"))
)
As you can see, most of the work is done by umxPath() (including setting labels). umxRAM wraps these paths up, takes the data = input, and
then internally sets sane start values. It also runs the model, and calls umxSummary().
Try it, or one of the several models in the examples at the bottom of this page.
nb: Because it uses the presence of a variable in the data to detect if a variable is latent or not, umxRAM needs data at build time.
Note also, a common error is to include data in the main list, a bit like saying lm(y ~ x + df) instead of lm(y ~ x, data = df).
String Syntax
Here is an example using lavaan syntax (for more, see umxLav2RAM())
m1 = umxRAM("mpg ~ wt + disp", data = mtcars)
Sketch mode
If you are at the "sketching" stage of theory consideration, umxRAM supports
setting data to a simple vector of manifest names.
As usual in umxRAM, any variables you refer to that are not in data are treated as latents.
m1 = umxRAM("sketch", data = c("A", "B"),
umxPath("C", to = c("A", "B"), values=.3),
umxPath("A", with = "B", values=.45),
umxPath(v.m. = c("A", "B")),
umxPath(v1m0 = "C")
)
plot(m1, means = FALSE)
Will create this figure:
umxRAM(
model = NA,
...,
data = NULL,
name = NA,
group = NULL,
group.equal = NULL,
suffix = "",
comparison = TRUE,
type = c("Auto", "FIML", "cov", "cor", "WLS", "DWLS", "ULS"),
weight = NULL,
allContinuousMethod = c("cumulants", "marginals"),
autoRun = getOption("umx_auto_run"),
tryHard = c("no", "yes", "ordinal", "search"),
std = FALSE,
refModels = NULL,
remove_unused_manifests = TRUE,
independent = NA,
setValues = TRUE,
optimizer = NULL,
verbose = FALSE,
std.lv = FALSE,
lavaanMode = c("sem", "lavaan"),
printTab = FALSE
)
model |
A model to update (or set to string to use as name for new model) |
... |
umxPaths, mxThreshold objects, etc. |
data |
data for the model. Can be an |
name |
A friendly name for the model |
group |
(optional) Column name to use for a multi-group model (default = NULL) |
group.equal |
In multi-group models, what to equate across groups (default = NULL: all free) |
suffix |
String to append to each label (useful if model will be used in a multi-group model) |
comparison |
Compare the new model to the old (if updating an existing model: default = TRUE) |
type |
One of "Auto", "FIML", "cov", "cor", "WLS", "DWLS", "ULS" |
weight |
Passes weight values to mxData |
allContinuousMethod |
"cumulants" or "marginals". Used in all-continuous WLS data to determine if a means model needed. |
autoRun |
Whether to run the model (default), or just to create it and return without running. |
tryHard |
Default ('no') uses normal mxRun. "yes" uses mxTryHard. Other options: "ordinal", "search" |
std |
Whether to show standardized estimates, raw (NULL print fit only) |
refModels |
pass in reference models if available. Use FALSE to suppress computing these if not provided. |
remove_unused_manifests |
Whether to remove variables in the data to which no path makes reference (defaults to TRUE) |
independent |
Whether the model is independent (default = NA) |
setValues |
Whether to generate likely good start values (Defaults to TRUE) |
optimizer |
optionally set the optimizer (default NULL does nothing) |
verbose |
Whether to tell the user what latents and manifests were created etc. (Default = FALSE) |
std.lv |
Whether to auto standardize latent variables when using string syntax (default = FALSE) |
lavaanMode |
Defaults when building out string syntax default = "sem" (alternative is "lavaan", with very few defaults) |
printTab |
(for string input, whether to output a table of paths (FALSE) |
WLS
umxRAM supports WLS estimation via the type argument ("WLS", "DWLS", or "ULS").
Important for ordinal data: If your data contains ordered factors, umxRAM will
automatically create the necessary mxThreshold objects. You do not need to add them manually.
For all-continuous data, use allContinuousMethod to control means modeling:
"cumulants" (default): Faster. No means model.
"marginals": Includes means and supports missing data.
Comparison for OpenMx users
umxRAM differs from OpenMx::mxModel() in the following ways:
You don't need to set type = "RAM".
You don't need to list manifestVars (they are detected from path usage).
You don't need to list latentVars (detected as anything in paths but not in mxData).
You don't need to create mxData when you already have a data.frame.
You add data with data = (as elsewhere in R, e.g. lm()).
You don't need to add labels: paths are automatically labelled "a_to_b" etc.
You don't need to set start values, they will be done for you.
You don't need to mxRun the model: it will run automatically, and print a summary.
You don't need to run summary: with autoRun=TRUE, it will print a summary.
You get a plot of the model with estimates on the paths, including multiple groups.
Less typing: umxPath() offers powerful verbs to describe paths.
Supports a subset of lavaan string input.
Start values. Currently, manifest variable means are set to the observed means,
residual variances are set to 80% of the observed variance of each variable,
and single-headed paths are set to a positive starting value (currently .9).
note: The start-value strategy is subject to improvement, and will be documented in the help for umxRAM().
Comparison with other software
Some SEM software does a lot of behind-the-scenes defaulting and path addition.
If you want this, umxRAM can read lavaan strings so you can carry on that way.
WLS, DWLS, and ULS in umxRAM vs lavaan
umxRAM supports three weighted least squares estimators via the type argument.
These control which weight matrix is used during estimation:
umx type | Weight matrix | Closest lavaan equivalent | Typical use |
"WLS" | Full weight matrix | estimator = "WLS" | Full-information WLS (computationally heavy) |
"DWLS" | Diagonal weight matrix | estimator = "DWLS" or the estimation step of "WLSMV" | Most common for ordinal data |
"ULS" | Identity matrix | estimator = "ULS" | Simpler unweighted estimation |
Important notes:
In lavaan, WLSMV combines diagonal weighting (DWLS-style estimation) with a mean-and-variance adjusted test statistic.
In umx/OpenMx, the weighting is controlled by type, while robust corrections to the chi-square and standard errors
are handled via its Jacobian, and information matrix.
When using ordinal data, make sure your variables are ordered factors. umxRAM will then automatically create the required mxThreshold objects.
OpenMx::mxModel()
https://tbates.github.io, https://github.com/tbates/umx
umxPath(), umxSummary(), plot(), parameters(), umxSuperModel(), umxLav2RAM()
Other Core Model Building Functions:
umx,
umxLISREL(),
umxMatrix(),
umxModify(),
umxPath(),
umxRAM_DE(),
umxSuperModel()
## Not run:
# ============================================
# = 1. Here's a simple example with raw data =
# ============================================
mtcars$litres = mtcars$disp/61.02
m1 = umxRAM("tim", data = mtcars,
umxPath(c("wt", "litres"), to = "mpg"),
umxPath("wt", with = "litres"),
umxPath(v.m. = c("wt", "litres", "mpg"))
)
# 2. Use parameters to see the parameter estimates and labels
parameters(m1)
# And umxSummary to get standardized parameters, CIs etc from the run model.
umxSummary(m1, std=TRUE)
# |name | Std.Estimate| Std.SE|CI |
# |:--------------|------------:|------:|:--------------------|
# |wt_to_mpg | -0.54| 0.17|-0.54 [-0.89, -0.2] |
# |disp_to_mpg | -0.36| 0.18|-0.36 [-0.71, -0.02] |
# |mpg_with_mpg | 0.22| 0.07|0.22 [0.08, 0.35] |
# |wt_with_wt | 1.00| 0.00|1 [1, 1] |
# |b1 | 0.89| 0.04|0.89 [0.81, 0.96] |
# |disp_with_disp | 1.00| 0.00|1 [1, 1] |
# 3. Of course you can plot the model
plot(m1)
plot(m1, std=TRUE, means=FALSE)
plot(m1, std = TRUE, means=FALSE, strip= TRUE, resid = "line")
# ===============================================
# = lavaan string example (more at ?umxLav2RAM) =
# ===============================================
m1 = umxRAM(data = mtcars, "#modelName
mpg ~ wt + disp")
# =======================
# = A multi-group model =
# =======================
mtcars$litres = mtcars$disp/61.02
m1 = umxRAM("tim", data = mtcars, group = "am",
umxPath(c("wt", "litres"), to = "mpg"),
umxPath("wt", with = "litres"),
umxPath(v.m. = c("wt", "litres", "mpg"))
)
# In this model, all parameters are free across the two groups.
# ====================================
# = A cov model, with steps laid out =
# ====================================
# *note*: The variance of displacement is in cubic inches and is very large.
# to help the optimizer, one might, say, multiply disp *.016 to work in litres
tmp = mtcars; tmp$disp= tmp$disp *.016
# We can just give the raw data and ask for it to be made into type cov:
m1 = umxRAM("tim", data = tmp, type="cov",
umxPath(c("wt", "disp"), to = "mpg"),
umxPath("wt", with = "disp"),
umxPath(var = c("mpg", "wt", "disp"))
)
# (see ?umxPath for more nifty options making paths...)
# =========================================
# = umxRAM can also accept mxData as data =
# =========================================
# For convenience, list up the manifests you will be using
selVars = c("mpg", "wt", "disp")
tmp = mtcars; tmp$disp= tmp$disp *.016
myCov = mxData(cov(tmp[, selVars]), type = "cov", numObs = nrow(mtcars) )
m1 = umxRAM("tim", data = myCov,
umxPath(c("wt", "disp"), to = "mpg"),
umxPath("wt", with = "disp"),
umxPath(var = selVars)
)
# =======================
# = umxRAM supports WLS =
# =======================
# 1. Run an all-continuous WLS model
mw = umxRAM("raw", data = mtcars[, c("mpg", "wt", "disp")],
type = "WLS", allContinuousMethod = "cumulants",
umxPath(var = c("wt", "disp", "mpg")),
umxPath(c("wt", "disp"), to = "mpg"),
umxPath("wt", with = "disp")
)
# 2. Switch to marginals to support means in WLS model
mw = umxRAM("raw", data = mtcars[, c("mpg", "wt", "disp")],
type = "WLS", allContinuousMethod= "marginals",
umxPath(var = c("wt", "disp", "mpg")),
umxPath(c("wt", "disp"), to = "mpg"),
umxPath("wt", with = "disp")
)
##########################
# Ordinal-data WLS model #
##########################
# 1. Generate Data
set.seed(12345)
n = 800
f = rnorm(n)
x1 = 0.75 * f + rnorm(n, sd = 0.66)
x2 = 0.80 * f + rnorm(n, sd = 0.60)
x3 = 0.70 * f + rnorm(n, sd = 0.71)
x4 = 0.85 * f + rnorm(n, sd = 0.53)
dat = data.frame(x1 = x1, x2 = x2, x3 = x3, x4 = x4)
# Turn into ordered categorical (4 categories)
dat[] = lapply(dat, function(x) cut(x, breaks = 4, labels = FALSE))
dat[] = lapply(dat, ordered)
# 1. Model in lavaan
model = ' f =~ x1 + x2 + x3 + x4 '
lav1 = cfa(model, data = dat, ordered = names(dat), estimator = "WLSMV")
# 2. Model in umxRAM
# todo: Note if not clear: Data can be raw, or mxData()
# todo: implement m.v. as a synonym for v.m.?
m1 = umxRAM("WLS_umx", data = dat, type = "WLS", allContinuousMethod = "cumulants",
# or "marginals"
umxPath("f", to = c("x1", "x2", "x3", "x4") ),
umxPath(v.m. = "f"),
umxPath(v.m. = c("x1", "x2", "x3", "x4"))
)
# ===============================
# = Using umxRAM in Sketch mode =
# ===============================
# No data needed: just list variable names!
# Resulting model will be plotted automatically
m1 = umxRAM("what does unique pairs do, I wonder", data = c("A", "B", "C"),
umxPath(unique.pairs = c("A", "B", "C"))
)
m1 = umxRAM("ring around the roses", data = c("B", "C"),
umxPath(fromEach = c("A", "B", "C"))
)
m1 = umxRAM("fromEach with to", data = c("B", "C"),
umxPath(fromEach = c("B", "C"), to= "D")
)
m1 = umxRAM("CFA_sketch", data = paste0("x", 1:4),
umxPath("g", to = paste0("x", 1:4)),
umxPath(var = paste0("x", 1:4)),
umxPath(v1m0 = "g")
)
# =================================================
# = This is an example of using your own labels: =
# umxRAM will not over-ride them =
# =================================================
m1 = umxRAM("tim", data = mtcars, type="cov",
umxPath(c("wt", "disp"), to = "mpg"),
umxPath(cov = c("wt", "disp"), labels = "b1"),
umxPath(var = c("wt", "disp", "mpg"))
)
omxCheckEquals(m1$S$labels["disp", "wt"], "b1") # label preserved
m1$S$labels
# mpg wt disp
# mpg "mpg_with_mpg" "mpg_with_wt" "disp_with_mpg"
# wt "mpg_with_wt" "wt_with_wt" "b1"
# disp "disp_with_mpg" "b1" "disp_with_disp"
parameters(m1)
# ===========
# = Weights =
# ===========
# toy example weighting rows by cylinders.
mtcars$litres = mtcars$disp/61.02
m1 = umxRAM("tim", data = mtcars, weight= "cyl",
umxPath(c("wt", "litres"), to = "mpg"),
umxPath("wt", with = "litres"),
umxPath(v.m. = c("wt", "litres", "mpg"))
)
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.