Ordinal variables in lavaan: Difference between ordered=TRUE and estimator=DWLS

1,657 views
Skip to first unread message

Linda Michelle

unread,
May 11, 2021, 5:33:47 AM5/11/21
to lavaan
Hello everyone,

I am applying SEM using Lavaan on a dataset with ordinal variables. 
I read online that I should use the DWLS estimator for this. 

I have tried two different ways of getting the results:

1) sem(sem(MyModel, MyData, ordered=TRUE)
2) sem(MyModel,MyData,estimator="DWLS")

In both cases, the DWLS estimator is used with optimisation method NLMINB.

However, the parameters and goodness-of-fit measures are completely different for both outputs. 

Does anyone know what the difference is between these two methods and which one I should use?



Rick Hass

unread,
May 13, 2021, 9:57:20 AM5/13/21
to lavaan
Hi,
I think your answer may be down the bottom here: https://lavaan.ugent.be/tutorial/cat.html 

Such that in specifying order = TRUE, you're getting the mean and variance adjusted test statistic and the full weight matrix (rather than diagonalized) is used for the parameter estimates. When specifying DWLS, without the ordered argument, those two things down happen, thus different fit measures (fit function) and different parameter estimates.

As far as what to use, that's your choice! If you want to truly model the indicators as ordinal, I'd go with ordered = TRUE.

-R

Saeed Abbas Shah

unread,
Dec 12, 2021, 2:04:05 PM12/12/21
to lavaan
Hi, 

Did you find the answer to your question because I am also facing same problem?

If you know, kindly share your learning.

Thanks
Regards

Chesnut, Ryan

unread,
Dec 12, 2021, 3:04:26 PM12/12/21
to lav...@googlegroups.com
In the second instance, it doesn’t look like any variables are declared ordered, so lavaan is using the DWLS estimator but treating the data as continuous. If you have ordered data, the first option would be preferable because it tells lavaan to treat the data as ordered.

Sent from my iPhone

On Dec 12, 2021, at 2:04 PM, Saeed Abbas Shah <s.a...@iba-suk.edu.pk> wrote:

Hi, 
--
You received this message because you are subscribed to the Google Groups "lavaan" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lavaan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/1944d6a7-d9a6-4596-9b34-61ca3a8aa0c3n%40googlegroups.com.

Shu Fai Cheung

unread,
Dec 12, 2021, 10:13:05 PM12/12/21
to lavaan
I am not contributing any new information. Just share two examples to illustrate others' responses:

library(lavaan)
#> This is lavaan 0.6-9
#> lavaan is FREE software! Please report any bugs.
# Round the indicator scores
vnames <- paste0("x", 1:6)
HolzingerSwineford1939[, vnames] <- round(HolzingerSwineford1939[, vnames])
lapply(HolzingerSwineford1939[, vnames], table)
#> $x1
#>
#>  1  2  3  4  5  6  7  8
#>  1  4 27 73 92 84 16  4
#>
#> $x2
#>
#>   2   4   5   6   7   8   9
#>   1  17  72 127  39  36   9
#>
#> $x3
#>
#>   0   1   2   3   4
#>  11  73 113  46  58
#>
#> $x4
#>
#>   0   1   2   3   4   5   6
#>   3  20  60 127  56  25  10
#>
#> $x5
#>
#>  1  2  3  4  5  6  7
#>  3 30 42 89 62 72  3
#>
#> $x6
#>
#>   0   1   2   3   4   5   6
#>   6  79 117  65  20  11   3
# Fit a CFA model
HS.model <- ' visual  =~ x1 + x2 + x3
              textual =~ x4 + x5 + x6'

# "ordered" only
fit1 <- cfa(HS.model, data = HolzingerSwineford1939, ordered = TRUE)
summary(fit1)
#> lavaan 0.6-9 ended normally after 18 iterations
#>
#>   Estimator                                       DWLS
#>   Optimization method                           NLMINB
#>   Number of model parameters                        42
#>                                                      
#>   Number of observations                           301
#>                                                      
#> Model Test User Model:
#>                                               Standard      Robust
#>   Test Statistic                                11.546      19.813
#>   Degrees of freedom                                 8           8
#>   P-value (Chi-square)                           0.173       0.011
#>   Scaling correction factor                                  0.625
#>   Shift parameter                                            1.336
#>        simple second-order correction                            
#>
#> Parameter Estimates:
#>
#>   Standard errors                           Robust.sem
#>   Information                                 Expected
#>   Information saturated (h1) model        Unstructured
#>
#> Latent Variables:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>   visual =~                                          
#>     x1                1.000                          
#>     x2                0.461    0.089    5.180    0.000
#>     x3                0.613    0.105    5.837    0.000
#>   textual =~                                          
#>     x4                1.000                          
#>     x5                1.022    0.047   21.578    0.000
#>     x6                0.989    0.042   23.351    0.000
#>
#> Covariances:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>   visual ~~                                          
#>     textual           0.326    0.044    7.349    0.000
#>
#> Intercepts:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>    .x1                0.000                          
#>    .x2                0.000                          
#>    .x3                0.000                          
#>    .x4                0.000                          
#>    .x5                0.000                          
#>    .x6                0.000                          
#>     visual            0.000                          
#>     textual           0.000                          
#>
#> Thresholds:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>     x1|t1            -2.714    0.331   -8.193    0.000
#>     x1|t2            -2.129    0.179  -11.928    0.000
#>     x1|t3            -1.246    0.097  -12.850    0.000
#>     x1|t4            -0.388    0.074   -5.223    0.000
#>     x1|t5             0.397    0.074    5.337    0.000
#>     x1|t6             1.503    0.111   13.479    0.000
#>     x1|t7             2.218    0.194   11.444    0.000
#>     x2|t1            -2.714    0.331   -8.193    0.000
#>     x2|t2            -1.556    0.115  -13.508    0.000
#>     x2|t3            -0.527    0.076   -6.925    0.000
#>     x2|t4             0.586    0.077    7.600    0.000
#>     x2|t5             1.039    0.088   11.736    0.000
#>     x2|t6             1.882    0.145   12.989    0.000
#>     x3|t1            -1.792    0.135  -13.244    0.000
#>     x3|t2            -0.586    0.077   -7.600    0.000
#>     x3|t3             0.397    0.074    5.337    0.000
#>     x3|t4             0.868    0.083   10.434    0.000
#>     x4|t1            -2.328    0.216  -10.785    0.000
#>     x4|t2            -1.430    0.107  -13.383    0.000
#>     x4|t3            -0.596    0.077   -7.712    0.000
#>     x4|t4             0.518    0.076    6.812    0.000
#>     x4|t5             1.194    0.095   12.619    0.000
#>     x4|t6             1.835    0.140   13.131    0.000
#>     x5|t1            -2.328    0.216  -10.785    0.000
#>     x5|t2            -1.228    0.096  -12.775    0.000
#>     x5|t3            -0.677    0.079   -8.601    0.000
#>     x5|t4             0.113    0.073    1.553    0.120
#>     x5|t5             0.677    0.079    8.601    0.000
#>     x5|t6             2.328    0.216   10.785    0.000
#>     x6|t1            -2.055    0.167  -12.296    0.000
#>     x6|t2            -0.576    0.077   -7.488    0.000
#>     x6|t3             0.443    0.075    5.906    0.000
#>     x6|t4             1.211    0.095   12.698    0.000
#>     x6|t5             1.680    0.125   13.447    0.000
#>     x6|t6             2.328    0.216   10.785    0.000
#>
#> Variances:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>    .x1                0.222                          
#>    .x2                0.834                          
#>    .x3                0.708                          
#>    .x4                0.266                          
#>    .x5                0.234                          
#>    .x6                0.283                          
#>     visual            0.778    0.145    5.371    0.000
#>     textual           0.734    0.046   15.967    0.000
#>
#> Scales y*:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>     x1                1.000                          
#>     x2                1.000                          
#>     x3                1.000                          
#>     x4                1.000                          
#>     x5                1.000                          
#>     x6                1.000
lavInspect(fit1, "ordered")
#> [1] "x1" "x2" "x3" "x4" "x5" "x6"
# "DWLS" only
fit2 <- cfa(HS.model, data = HolzingerSwineford1939, estimator = "DWLS")
summary(fit2)
#> lavaan 0.6-9 ended normally after 36 iterations
#>
#>   Estimator                                       DWLS
#>   Optimization method                           NLMINB
#>   Number of model parameters                        13
#>                                                      
#>   Number of observations                           301
#>                                                      
#> Model Test User Model:
#>                                                      
#>   Test statistic                                 8.480
#>   Degrees of freedom                                 8
#>   P-value (Chi-square)                           0.388
#>
#> Parameter Estimates:
#>
#>   Standard errors                             Standard
#>   Information                                 Expected
#>   Information saturated (h1) model        Unstructured
#>
#> Latent Variables:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>   visual =~                                          
#>     x1                1.000                          
#>     x2                0.457    0.090    5.051    0.000
#>     x3                0.571    0.105    5.452    0.000
#>   textual =~                                          
#>     x4                1.000                          
#>     x5                1.050    0.124    8.484    0.000
#>     x6                0.952    0.110    8.664    0.000
#>
#> Covariances:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>   visual ~~                                          
#>     textual           0.422    0.056    7.605    0.000
#>
#> Variances:
#>                    Estimate  Std.Err  z-value  P(>|z|)
#>    .x1                0.382    0.241    1.585    0.113
#>    .x2                1.182    0.133    8.859    0.000
#>    .x3                0.939    0.109    8.639    0.000
#>    .x4                0.386    0.188    2.049    0.040
#>    .x5                0.683    0.197    3.470    0.001
#>    .x6                0.388    0.180    2.150    0.032
#>     visual            1.005    0.213    4.715    0.000
#>     textual           0.983    0.146    6.717    0.000
lavInspect(fit2, "ordered")
#> character(0)

In the first example (fit1), the argument order is used. It will automatically compute the tetrachoric or polychoric correlations for ordinal variables, add thresholds and the mean structure to the model, use DWLS as the estimator, set standard error to "robust.sem", and report robust fit measures.

In the second example (fit2), only estimator = "DWLS" is used. lavaan will do only what is instructed: setting the estimator to "DWLS". lavInspect() result confirms that no variables are treated as ordinal.

Therefore, just use order (set it to TRUE, or specify the ordinal variables if only some of them are ordinal). It will configure other arguments accordingly. Do not manually set those related arguments unless you do want to override the default options for ordinal variables.

Hope this helps.

-- Shu Fai
Reply all
Reply to author
Forward
0 new messages