simsem / semTools

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

reliability doesn't work when model has observed variables #86

Closed mattansb closed 3 years ago

mattansb commented 3 years ago
library(lavaan)
library(semTools)

m1 <- ' 
   visual =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
    speed =~ x7 + x8 + x9 

  visual ~~ agemo
'

fit1 <- cfa(m1, data = HolzingerSwineford1939)
reliability(fit1)
#> Warning in (apply(ly[[i]], 2, sum)^2) * diag(ve[[i]]): longer object length is
#> not a multiple of shorter object length
#> Error in ly[[i]] %*% ve[[i]]: non-conformable arguments

Not sure if this is deliberate, as in the docs it does say "object: ... expected to contain only exogenous common factors", but seeing as how the workaround is to fit single-indicator latent variables, which are the same model - is there a reason not to allow this? 👆

m2 <- ' 
   visual =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
    speed =~ x7 + x8 + x9 

    AGEMO =~ 1 * agemo

  visual ~~ AGEMO
   AGEMO ~~ 0 * textual + 0 * speed
'

fit2 <- cfa(m2, data = HolzingerSwineford1939)
reliability(fit2)
#>           visual   textual     speed
#> alpha  0.6261171 0.8827069 0.6884550
#> omega  0.6252368 0.8851833 0.6879509
#> omega2 0.6252368 0.8851833 0.6879509
#> omega3 0.6117243 0.8850713 0.6861618
#> avevar 0.3705124 0.7210349 0.4247314

Created on 2021-02-28 by the reprex package (v1.0.0)

TDJorgensen commented 3 years ago

Not sure if this is deliberate, as in the docs it does say "object: ... expected to contain only exogenous common factors"

That just absolved Sunthud (and now me) from trying to guess all the myriad different types of SEMs that people might want to use to calculate reliability, instead of simply fitting a measurement model to evaluate the quality of a measurement instrument, then fitting other models to address other research questions. Internally, we simply use lavInspect(fit, "cov.lv") instead of lavInspect(fit, "est")$psi to allow models to have structural regressions (in which case $psi is a residual rather than marginal covariance matrix). If you don't explicitly specify an exogenous covariate as a single-indicator factor, then lavaan assumes you don't want to think of it as a latent variable (even though that is simply the hack to get it to work in a LISREL representation). So it drops the internally created single-indicator constructs from lavInspect(fit, "cov.lv"), although the explicitly requested factor-loading matrix (and any other matrices from lavInspect(fit, "est")) do still conform to the underlying model with a single-indicator factor.

mattansb commented 3 years ago

I see. I wonder if it could be made to work with another hack that makes latent<->observer covariance work:

m2 <- ' 
   visual =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
    speed =~ x7 + x8 + x9 

  # regress on self
  agemo ~ 1 * agemo

  visual ~~ agemo
'

fit2 <- cfa(m2, data = HolzingerSwineford1939)
reliability(fit2)
#> Error in ly[[i]] %*% ve[[i]] : non-conformable arguments
#> In addition: Warning message:
#> In (apply(ly[[i]], 2, sum)^2) * diag(ve[[i]]) :
#>   longer object length is not a multiple of shorter object length
TDJorgensen commented 3 years ago

I wonder if it could be made to work with another hack

The error you posted suggests the answer is no. I explained that this function is meant for measurement models. What are you trying to accomplish?

mattansb commented 3 years ago

I am trying to fit a measurement model with a covariance between an observed and latent variables - I'm just using a different hack to allow this to happen 🤷‍♂️

TDJorgensen commented 3 years ago

I am trying to fit a measurement model with a covariance between an observed and latent variables

I can see that, but substantively, why is it so important to add variables to your model that have nothing to do with estimating the reliability of a composite? If the observed variable is also part of the composite, then model it as a single-indicator construct and set return.total=TRUE and dropSingle=FALSE.

mattansb commented 3 years ago

I see. So single-indicator is the only way to go on this one. Got it - thanks!