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.20) 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 54.26
#> Degrees of Freedom (Chi-square) 33
#> P-value (Chi-square) 0.011
#> RMSEA 0.018
#>
#> 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 penalized
#>
#> Latent Variables:
#> Estimate Std.Error z.value P(>|z|)
#> X =~
#> x1 0.933 0.061 15.176 0.000
#> x2 0.900 0.064 14.030 0.000
#> x3 0.918 0.061 15.156 0.000
#> Z =~
#> z1 0.920 0.062 14.888 0.000
#> z2 0.905 0.063 14.321 0.000
#> z3 0.909 0.062 14.598 0.000
#> Y =~
#> y1 0.975 0.057 17.212 0.000
#> y2 0.958 0.066 14.511 0.000
#> y3 0.965 0.062 15.529 0.000
#>
#> Regressions:
#> Estimate Std.Error z.value P(>|z|)
#> Y ~
#> X 0.433 0.044 9.838 0.000
#> Z 0.382 0.037 10.265 0.000
#> X:Z 0.484 0.152 3.176 0.001
#>
#> Covariances:
#> Estimate Std.Error z.value P(>|z|)
#> X ~~
#> Z 0.197 0.035 5.664 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