| umxCompare | R Documentation |
OpenMx::mxModel()s, nicely formatted.umxCompare compares two or more OpenMx::mxModel()s. It has several nice features:
Direct control of precision via digits=. p-values use APA style.
Report = directs publication to your chosen format: markdown, html, latex.
Columns arranged to make for easy visual comparison.
report = 'inline', includes a summary sentence suitable for your report.
report = "html" opens a web table in your browser to paste into a word processor.
Interpreting fit under WLS/DWLS and Genomic SEM
Hu & Bentler (1999) style cutoffs (e.g. CFI > .95, RMSEA < .06) were developed for
maximum likelihood with continuous data. They do not transfer to WLS/DWLS
(Shi et al., 2020), and still less to Genomic SEM (DWLS on LDSC genetic
covariances with an estimated sampling covariance, often with bookkeeping numObs = 1).
Incremental indices (CFI, TLI, NFI, ...) compare the model to an independence baseline under the same weight matrix. That baseline behaves differently than under ML. Report CFI/TLI only descriptively; do not apply conventional cutoffs.
Absolute fit: SRMR (and residual matrices) is preferred. SRMR lives on a standardized residual metric and is less hostage to weight-matrix / N scaling. Rough guide: SRMR < 0.10 suggests acceptable residual structure (not a hard law).
RMSEA folds in chi-square scaling and N; it is often misleading for WLS and especially for GSEM. Do not use the ML cutoff of < .06.
Nested model building: prefer scaled chi-square difference tests and DeltaSRMR
over DeltaCFI alone (see Details for what umxCompare computes).
umxCompare(
base = NULL,
comparison = NULL,
all = TRUE,
digits = 3,
report = c("markdown", "html", "inline"),
compareWeightedAIC = FALSE,
silent = FALSE,
file = "tmp.html",
uncertainty = c("none", "SE", "MLR", "CI")
)
base |
The base |
comparison |
The model (or list of models) which will be compared for fit with the base model (can be empty) |
all |
Whether to make all possible comparisons if there is more than one base model (defaults to T) |
digits |
rounding for p-values etc. |
report |
"markdown" (default), "inline" (a sentence suitable for inclusion in a paper), or "html". create a web table and open your default browser. (handy for getting tables into Word, and other text systems!) |
compareWeightedAIC |
Show the Wagenmakers AIC weighted comparison (default = FALSE) |
silent |
(don't print, just return the table as a dataframe (default = FALSE) |
file |
file to write html too if report = "html" (defaults to "tmp.html") |
uncertainty |
What type of parameter uncertainty to report: "SE" (standard ML standard errors), "MLR" (robust standard errors and robust fit), "CI" (profile likelihood confidence intervals), or "none" (none). |
What umxCompare does for WLS
Refuses mixed WLS vs ML comparisons (same engine required).
Continuous WLS with cached implied_jacobian:
Table Chi is the same Satorra-Bentler (2010) scaled omnibus as umxSummary()
(F/c from output$fit), not OpenMx Browne residual output$chi
(those two differ under DWLS). Saturated residual df reports Chi = 0, CFI = 1, RMSEA = 0.
Nested diffFit is SB-2010 scaled \Delta F = F_{nested} - F_{base}
(requires both models at comparable minima of the same WLS objective: same moments,
useWeight, and N). If F_{nested} < F_{base} (often multigroup
optimization), diffFit is NA with a warning - not a negative chi-square with p = 1.
Genomic SEM (MxModelGSEM): nested difference on the GSEM DWLS chi-square
scale (same discrepancy as the structural fit; not a substitute for ML LRT).
If LDSC matrices were nearPD-smoothed, a fiduciary warning notes that difference
tests may look artificially precise.
Table also reports SRMR / DeltaSRMR (preferred absolute residual summary) and CFI / DeltaCFI (descriptive only). AIC may appear but is not a primary GSEM decision rule under asymptotic / bookkeeping N.
Ordinal WLS is a separate track: robust CFI/TLI/RMSEA use Savalei (2021) catML
corrections in umxSummary(); Hu-Bentler cutoffs can apply to those robust indices.
That exception does not apply to continuous WLS or Genomic SEM.
Best practice: report estimates with SEs, SRMR (and residuals), nested SB/GSEM difference tests, and avoid single-number "good fit" claims from CFI or RMSEA.
Constraints and the EP column
EP is OpenMx's count of free parameters, summary(model)$estimatedParameters.
Equality OpenMx::mxConstraint()s are not removed from that count. OpenMx adds
their rows to observedStatistics, and degrees of freedom already include them.
A common-pathway model that sets each factor with A + C + E = 1 can therefore
show a larger EP than an independent-pathway model while \Delta df is 0. Both
numbers are the OpenMx counts. When sum(summary(model)$constraints) is above 0,
umxCompare adds one line for that model:
Note: df for 'CP' reflects 3 constraints: 51 estimated parameters (48 effective after constraints).
With silent = TRUE, the lines are attr(table, "constraintNotes"), one element
per model. A comparison in which no model has an equality constraint does not
set that attribute. Inequality constraints contribute 0 and do not produce a line.
umxSummary(), umxRAM(),umxCompare()
Other Model Summary and Comparison:
umx,
umxEquate(),
umxMI(),
umxReduce(),
umxSetParameters(),
umxSummary(),
xmu_compare_WLS(),
xmu_robust_WLS_fit()
## Not run:
require(umx)
data(demoOneFactor)
manifests = names(demoOneFactor)
m1 = umxRAM("One Factor", data = demoOneFactor, type = "cov",
umxPath("G", to = manifests),
umxPath(var = manifests),
umxPath(var = "G", fixedAt = 1)
)
m2 = umxModify(m1, update = "G_to_x2", name = "drop_path_2_x2")
umxCompare(m1, m2)
umxCompare(m1, m2, report = "inline") # Add English-sentence descriptions
umxCompare(m1, m2, report = "html") # Open table in browser
# Two comparison models
m3 = umxModify(m2, update = "G_to_x3", name = "drop_path_2_x2_and_3")
umxCompare(m1, c(m2, m3))
umxCompare(m1, c(m2, m3), compareWeightedAIC = TRUE)
umxCompare(c(m1, m2), c(m2, m3), all = TRUE)
manifests = names(demoOneFactor)
m1 = umxRAM("WLS", data = demoOneFactor, type = "DWLS",
umxPath("G", to = manifests),
umxPath(var = manifests),
umxPath(var = "G", fixedAt = 1)
)
m2 = umxModify(m1, update = "G_to_x2", name = "drop_path_2_x2")
umxCompare(m1, m2)
umxCompare(m1, m2, report = "inline") # Add English-sentence descriptions
umxCompare(m1, m2, report = "html") # Open table in browser
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.