modsem implements a Monte-Carlo correction for LMS and
QML models with ordinal data. Here we refer to these informally as
MC-LMS-ORD and MC-QML-ORD.
The MC-LMS-ORD and MC-QML-ORD algorithms
are based on Slupphaug, Mehmetoglu,
and Mittner (2026) For a more direct implementation of the original
algorithm, we recommend checking out the plssem
package.
Example
Here we ordinalize the data in the oneInt dataset.
ordinalize <- function(x, probs = c(0, 0.35, 0.7, 1)) {
x <- (x - mean(x)) / sd(x)
cut(
x,
breaks = stats::quantile(x, probs = probs),
include.lowest = TRUE,
ordered_result = TRUE
)
}
oneIntOrd <- as.data.frame(lapply(oneInt, ordinalize))Now we can estimate our model, indicating which variables are
ordinal, using the ordered= argument.
model <- "
X =~ x1 + x2 + x3
Z =~ z1 + z2 + z3
Y =~ y1 + y2 + y3
Y ~ X + Z + X:Z
"
fit_lms_ord <- modsem(
model,
data = oneIntOrd,
method = "lms",
ordered = colnames(oneIntOrd)
)
summary(fit_lms_ord)
#>
#> modsem (1.0.21) ended normally after 81 iterations
#>
#> Estimator MC-LMS
#> Optimization method ROBBINS-MONRO
#> Naive optimization method EMA-NLMINB
#> Number of model parameters 13
#>
#> Number of observations 2000
#>
#> Naive Loglikelihood and Information Criteria:
#> Naive Loglikelihood -19223.44
#> Naive Akaike (AIC) 38472.87
#> Naive Bayesian (BIC) 38545.68
#>
#> Numerical Integration:
#> Points of integration (per dim) 24
#> Dimensions 1
#> Total points of integration 24
#>
#> Fit Measures for Baseline Model (H0):
#> Standard
#> Chi-square 41.87
#> Degrees of Freedom (Chi-square) 33
#> P-value (Chi-square) 0.139
#> RMSEA 0.012
#>
#> Naive Loglikelihood -19343.47
#> Naive Akaike (AIC) 38710.94
#> Naive Bayesian (BIC) 38778.15
#>
#> Comparative Fit to H0 (LRT test):
#> Loglikelihood change 120.04
#> Difference test (D) 240.07
#> Degrees of freedom (D) 1
#> P-value (D) 0.000
#>
#>
#> Parameter Estimates:
#> Coefficients standardized
#> Information observed
#> Standard errors standard
#>
#> Latent Variables:
#> Estimate Std.Error z.value P(>|z|)
#> X =~
#> x1 0.933 0.007 130.789 0.000
#> x2 0.900 0.008 110.964 0.000
#> x3 0.918 0.007 134.462 0.000
#> Z =~
#> z1 0.920 0.007 123.281 0.000
#> z2 0.905 0.008 108.270 0.000
#> z3 0.909 0.008 120.189 0.000
#> Y =~
#> y1 0.975 0.003 291.885 0.000
#> y2 0.958 0.005 182.115 0.000
#> y3 0.965 0.004 223.852 0.000
#>
#> Regressions:
#> Estimate Std.Error z.value P(>|z|)
#> Y ~
#> X 0.433 0.020 21.884 0.000
#> Z 0.382 0.021 17.763 0.000
#> X:Z 0.484 0.025 19.530 0.000
#>
#> Covariances:
#> Estimate Std.Error z.value P(>|z|)
#> X ~~
#> Z 0.197 0.025 7.841 0.000
#>
#> Thresholds:
#> Estimate Std.Error z.value P(>|z|)
#> x1|t1 -0.385
#> x1|t2 0.524
#> x2|t1 -0.385
#> x2|t2 0.524
#> x3|t1 -0.385
#> x3|t2 0.524
#> z1|t1 -0.385
#> z1|t2 0.524
#> z2|t1 -0.385
#> z2|t2 0.524
#> z3|t1 -0.385
#> z3|t2 0.524
#> y1|t1 -0.385
#> y1|t2 0.524
#> y2|t1 -0.385
#> y2|t2 0.524
#> y3|t1 -0.385
#> y3|t2 0.524
#>
#> Variances:
#> Estimate Std.Error z.value P(>|z|)
#> .x1 0.129
#> .x2 0.191
#> .x3 0.158
#> .z1 0.154
#> .z2 0.181
#> .z3 0.174
#> .y1 0.049
#> .y2 0.083
#> .y3 0.068
#> X 1.000
#> Z 1.000
#> .Y 0.367