yrosseel / lavaan

an R package for structural equation modeling and more
http://lavaan.org
413 stars 99 forks source link

sample.th= not indexed properly #366

Open TDJorgensen opened 5 days ago

TDJorgensen commented 5 days ago

Here is a problem that will RARELY show up, when users call lavaan() with summary statistics for ordinal data, so the sample.th= argument is included. The hidden lav_samplestats_from_moments() function assigns (on Lines 1461 and 1489) the values from that argument to a vector that is eventually returned in the lavSampleStats-class object. When the modeled variables include a mixture of ordered and numeric variables, then thresholds and (negative) means are separately assigned to the vector. The threshold indices in ord.idx are used on the left-hand side of the assignment, but not on the right. So unless the only ordered variables happen to be at the beginning of the ov.names list, then (negative) sample means on the right-hand side are assigned instead of thresholds, with a warning about a mismatch in length.

library(lavaan.mi)
data(HS20imps)
impSubset1 <- lapply(HS20imps, "[", i = paste0("x", 1:9)) # only modeled variables
# discretize x4 and x5 (NOT the first two variables)
HS3cat_v2 <- lapply(impSubset1, function(df) {
    df[, 4:5] <- lapply(df[, 4:5], cut, breaks = 3, labels = FALSE)
    return(df)
})
prePooledData4 <- poolSat(HS3cat_v2, ordered = c("x4", "x5"))

fit_example3 <- lavaan::efa(data = prePooledData4, nfactors = 3, rotation = "promax",
                            output = "lavaan",
                            ordered = c("x4", "x5"), # warning unless all/none (TRUE / FALSE),
                            conditional.x = FALSE)   # also when conditional.x = TRUE
summary(fit_example3) # notice the first 3 thresholds are the first 3 intercepts

As this reprex indicates, pooled summary statistics are being passed to efa() to avoid the problem of synchronizing extracted factors across imputations.

I added ord.idx to the right-hand side of the assignment, avoiding the problem and warning. I'll send a PR.