Skip to contents
library(modsem)
#> This is modsem (1.0.22). Please report any bugs!
set.seed(2938472)

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.22) ended normally after 75 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                                     51.69
#>   Degrees of Freedom (Chi-square)                   33
#>   P-value (Chi-square)                           0.020
#>   RMSEA                                          0.017
#>                                                       
#>   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.008  116.248    0.000
#>     x2              0.900      0.008  113.581    0.000
#>     x3              0.920      0.007  128.833    0.000
#>   Z =~          
#>     z1              0.920      0.008  112.731    0.000
#>     z2              0.903      0.007  122.984    0.000
#>     z3              0.906      0.009  104.988    0.000
#>   Y =~          
#>     y1              0.975      0.004  241.284    0.000
#>     y2              0.956      0.004  222.604    0.000
#>     y3              0.965      0.006  172.895    0.000
#> 
#> Regressions:
#>                  Estimate  Std.Error  z.value  P(>|z|)
#>   Y ~           
#>     X               0.438      0.022   19.487    0.000
#>     Z               0.382      0.023   16.931    0.000
#>     X:Z             0.480      0.031   15.231    0.000
#> 
#> Covariances:
#>                  Estimate  Std.Error  z.value  P(>|z|)
#>   X ~~          
#>     Z               0.189      0.027    7.087    0.000
#> 
#> Thresholds:
#>                  Estimate  Std.Error  z.value  P(>|z|)
#>     x1|t1          -0.377      0.031  -11.983    0.000
#>     x1|t2           0.500      0.029   17.275    0.000
#>     x2|t1          -0.392      0.028  -14.045    0.000
#>     x2|t2           0.506      0.029   17.595    0.000
#>     x3|t1          -0.386      0.030  -12.885    0.000
#>     x3|t2           0.520      0.029   17.934    0.000
#>     z1|t1          -0.360      0.029  -12.210    0.000
#>     z1|t2           0.528      0.030   17.584    0.000
#>     z2|t1          -0.374      0.030  -12.619    0.000
#>     z2|t2           0.534      0.032   16.779    0.000
#>     z3|t1          -0.364      0.028  -13.077    0.000
#>     z3|t2           0.543      0.029   18.589    0.000
#>     y1|t1          -0.344      0.024  -14.263    0.000
#>     y1|t2           0.487      0.030   16.053    0.000
#>     y2|t1          -0.366      0.024  -15.391    0.000
#>     y2|t2           0.484      0.031   15.844    0.000
#>     y3|t1          -0.350      0.023  -15.548    0.000
#>     y3|t2           0.482      0.034   14.300    0.000
#> 
#> Variances:
#>                  Estimate  Std.Error  z.value  P(>|z|)
#>    .x1              0.131                             
#>    .x2              0.191                             
#>    .x3              0.154                             
#>    .z1              0.154                             
#>    .z2              0.185                             
#>    .z3              0.179                             
#>    .y1              0.049                             
#>    .y2              0.085                             
#>    .y3              0.070                             
#>     X               1.000                             
#>     Z               1.000                             
#>    .Y               0.368