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.23) ended normally after 57 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 30.62
#> Degrees of Freedom (Chi-square) 33
#> P-value (Chi-square) 0.586
#> RMSEA 0.000
#>
#> 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 mc-delta
#>
#> Latent Variables:
#> Estimate Std.Error z.value P(>|z|)
#> X =~
#> x1 0.932 0.007 136.803 0.000
#> x2 0.900 0.007 129.262 0.000
#> x3 0.919 0.007 126.789 0.000
#> Z =~
#> z1 0.919 0.008 113.945 0.000
#> z2 0.904 0.007 124.300 0.000
#> z3 0.908 0.008 108.882 0.000
#> Y =~
#> y1 0.975 0.004 261.362 0.000
#> y2 0.957 0.004 218.195 0.000
#> y3 0.964 0.004 230.458 0.000
#>
#> Regressions:
#> Estimate Std.Error z.value P(>|z|)
#> Y ~
#> X 0.434 0.020 21.340 0.000
#> Z 0.380 0.021 18.013 0.000
#> X:Z 0.485 0.027 17.832 0.000
#>
#> Covariances:
#> Estimate Std.Error z.value P(>|z|)
#> X ~~
#> Z 0.190 0.027 7.085 0.000
#>
#> Thresholds:
#> Estimate Std.Error z.value P(>|z|)
#> x1|t1 -0.387 0.027 -14.289 0.000
#> x1|t2 0.533 0.031 17.069 0.000
#> x2|t1 -0.387 0.030 -13.022 0.000
#> x2|t2 0.529 0.030 17.725 0.000
#> x3|t1 -0.394 0.029 -13.646 0.000
#> x3|t2 0.522 0.029 17.732 0.000
#> z1|t1 -0.390 0.030 -13.154 0.000
#> z1|t2 0.525 0.030 17.744 0.000
#> z2|t1 -0.381 0.030 -12.820 0.000
#> z2|t2 0.520 0.029 17.651 0.000
#> z3|t1 -0.393 0.031 -12.847 0.000
#> z3|t2 0.524 0.030 17.605 0.000
#> y1|t1 -0.322 0.025 -13.112 0.000
#> y1|t2 0.496 0.030 16.656 0.000
#> y2|t1 -0.325 0.025 -13.127 0.000
#> y2|t2 0.509 0.030 16.822 0.000
#> y3|t1 -0.323 0.026 -12.535 0.000
#> y3|t2 0.505 0.030 17.061 0.000
#>
#> Variances:
#> Estimate Std.Error z.value P(>|z|)
#> .x1 0.132
#> .x2 0.190
#> .x3 0.156
#> .z1 0.155
#> .z2 0.183
#> .z3 0.175
#> .y1 0.049
#> .y2 0.084
#> .y3 0.070
#> X 1.000
#> Z 1.000
#> .Y 0.369