simsem / semTools

Useful tools for structural equation modeling
75 stars 36 forks source link

measEq.syntax error in SEM model #83

Closed hynekcigler closed 3 years ago

hynekcigler commented 3 years ago

Hi, I have another bug, I am sorry :(

If any latent regression is present in measEq.syntax function (in the configural model definition), it is interpreted as the second-order loading (lambda matrix) instead of regression path (beta matrix). In parameter table, it is correctly named beta (column "mat"), but an operator (column op) is labeled as "=~" instead of ~, which causes several problems in estimation. For example, ID.fac is automatically set to ul, model is not identified etc.

I assume the problem is in the function lines 905, 935 (where op is searched to be =~ instead of \~) and several places around (e.g. equate.load, line 921?) etc. However, I am not sure how the function is built, so an error could be elsewhere.

See the script here:

mod <- "
A =~ I1+I2+I3
B =~ I4+I5+I6
C =~ I7+I8+I9
D =~ I10+I11+I12

C ~ A+B
D ~ A+B
"

x <- measEq.syntax(mod, parameterization = "theta", ordered=T, ID.fac = "std.lv", return.fit = F) ## see the warning
cat(as.character(x)) ## here is no regressions

y <- measEq.syntax(mod, parameterization = "theta", ordered=T, ID.fac = "std.lv", return.fit = T) ## see the warning
summary(y) ## there is no regressions, but instead there is a second order loading.

lavMatrixRepresentation(parTable(y))[,c("lhs","op","rhs","mat","row","col")] ## compare e.g. parameter 4 A =~ C (beta matrix, but with an operater "=~") 

I can fix it easily manually using cat(as.character(x)), but it is very annoying. Anyway, thank you for the function, it is really amazing!

TDJorgensen commented 3 years ago

This is a feature, not a bug. As the help-page states, this function is for writing syntax to testing invariance using multigroup CFA, so no structural regression model should be imposed on the latent variables (see the description of the configural.model= argument).

hynekcigler commented 3 years ago

@TDJorgensen My appologize. Thank you for a clarification!

However, it would be beneficial to provide any warning in such cases. It returns only Higher-order factors detected. ID.fac set to "ul". now, while it invisibly changes latent regression (beta matrix) to second-order factor (lamba matrix). I suggest to stop the function and provide warning.

TDJorgensen commented 3 years ago

it invisibly changes latent regression (beta matrix) to second-order factor (lamba matrix)

No, second-order loadings are in the beta matrix. Only when writing the syntax are the lambda and beta matrices concatenated so a single =~ operator can be used for all factor loadings. The operator may be arbitrary, but using the ~ operator would still require first defining a phantom factor using =~:

foo =~ a + b + c
# or equivalently
foo =~ 0
a + b + c ~ foo

it would be beneficial to provide any warning in such cases

Added.