- Am I doing this right?
- How do I interpret the output?
- Why are all intercepts 0?
- What does it mean that intercept, slope, and quadratic slope are not significant?
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/5f9bb835-84c4-4390-b659-33e6fef4d105n%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/8c2bc5a4-e34e-4526-a29b-0b662e94b644n%40googlegroups.com.
Dear Pat,As commented in the code (in the note directly above that line of code) this is done to force this factor loading to be free. I therefore pre-multiply it with NA, as a hint to Lavaan that the value of this parameter is still unknown.
I tried the growth and sem function and attached the two outputs as pdf. Using the sem function without i ~ 1 and s ~ 1 intercept and slope would be 0.I find it a bit spooky that the results differ when using different functions. Are you certain that I can trust the results of the sem function?
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/8668c7e6-8035-4d1d-8d8e-13034d1d61cbn%40googlegroups.com.
configural_boredom <- '# measurement modelboredom_0 =~ bos1_0 + bos1_0 + bos2_0 + bos3_0 + bos4_0 + bos5_0 + bos6_0boredom_1 =~ bos1_1 + bos1_1 + bos2_1 + bos3_1 + bos4_1 + bos5_1 + bos6_1boredom_2 =~ bos1_2 + bos1_2 + bos2_2 + bos3_2 + bos4_2 + bos5_2 + bos6_2fit_configural_boredom <- cfa(configural_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_configural_boredom, fit.measures = TRUE, standardized = TRUE)
weak_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2boredom_0 ~~ 1* boredom_0boredom_1 ~~ NA*boredom_1boredom_2 ~~ NA*boredom_2'fit_weak_boredom <- cfa(weak_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_weak_boredom, fit.measures = TRUE, standardized = TRUE)
strong_boredom <- '# measurement model
boredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2boredom_0 ~~ 1* boredom_0boredom_1 ~~ NA*boredom_1boredom_2 ~~ NA*boredom_2boredom_0 ~0*1boredom_1 ~NA*1boredom_2 ~NA*1'fit_strong_boredom <- cfa(strong_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_strong_boredom, fit.measures = TRUE, standardized = TRUE)
--
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/192ebed6-1314-4448-ad81-7ed220246ea3n%40googlegroups.com.
Is there a way to add Bonferroni correction to the p-values?
Since all of them are 0.000 and options(digits=10) does not work
--
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/da70b0b3-991a-44ab-93f1-4da1c29f1e26n%40googlegroups.com.
Do you have any arguments against users (or reviewers) why I should predict this slope anyways?
And is it common to report the variance including its p-value if I want to report the results of 3.?
--
You received this message because you are subscribed to a topic in the Google Groups "lavaan" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/lavaan/dNLXNaRFhzA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to lavaan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lavaan/34e0f0bf-8c86-4349-9c65-63f39a2df260n%40googlegroups.com.
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/eeff7dbf-1647-41e1-951b-16a10be002a0n%40googlegroups.com.
Do you already have an answer to this?> If I decide to add gender as a grouping variable, would I add this to the measurement invariance analysis as well?
ManuelI think you are mixing contrainst based on identification methods. You are setting the marker variable identification , and using constraints like fixed variance.Would make these changes, changes are highlightedlibrary(lavaan)
# * 2.1 Configural Invariance ---------------------------------------------
# note: to force this factor loading to be free, we pre-multiply it with NA, as a hint to lavaan that the value of this parameter is still unknown.configural_boredom <- '# measurement modelboredom_0 =~ bos1_0 + bos1_0 + bos2_0 + bos3_0 + bos4_0 + bos5_0 + bos6_0boredom_1 =~ bos1_1 + bos1_1 + bos2_1 + bos3_1 + bos4_1 + bos5_1 + bos6_1boredom_2 =~ bos1_2 + bos1_2 + bos2_2 + bos3_2 + bos4_2 + bos5_2 + bos6_2fit_configural_boredom <- cfa(configural_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_configural_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.2 Weak Invariance ---------------------------------------------------# model specification (additional constraints on latent factors)
# same factor loadings for each item over time
weak_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2boredom_0 ~~ 1* boredom_0
boredom_1 ~~ NA*boredom_1boredom_2 ~~ NA*boredom_2
'fit_weak_boredom <- cfa(weak_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_weak_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.3 Strong Invariance -------------------------------------------------# model specification (additional constraints on manifest intercepts)
strong_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2boredom_0 ~~ 1* boredom_0
boredom_1 ~~ NA*boredom_1boredom_2 ~~ NA*boredom_2
boredom_0 ~0*1boredom_1 ~NA*1boredom_2 ~NA*1'fit_strong_boredom <- cfa(strong_boredom, data = df1, missing = "FIML", estimator = "MLR", std.lv=T)summary(fit_strong_boredom, fit.measures = TRUE, standardized = TRUE)############Why are you building that function for the LRT between models? Becuase you are using the MLR estimator?lavaan methods of nested model comparison do the correct adjust for MLR, MLM, DWLS, etc, estimator. WIth the lavTestLRT() for nested model comparison. If you go into details, you will some options for adjustsments based on the estimator#########Last, when you have a bagative LV variance, for which latent variable is it? If it for the Intecept or slope might be an indicationg that this is not a random parameter but should be treated as fix, which can be odd on the SEM, but its standard in growth curves in MLM.On Wednesday, December 16, 2020 at 6:00:26 PM UTC+1 mailsc...@gmail.com wrote:Dear Pat,You are absolutely right! I am getting there…I changed my code accordingly to establish longitudinal strong measurement invariance as follows:# exploring measurement invariance over timelibrary(lavaan)
# * 2.1 Configural Invariance ---------------------------------------------
# note: to force this factor loading to be free, we pre-multiply it with NA, as a hint to lavaan that the value of this parameter is still unknown.configural_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + bos1_0 + bos2_0 + bos3_0 + bos4_0 + bos5_0 + bos6_0boredom_1 =~ lambda0*bos1_1 + bos1_1 + bos2_1 + bos3_1 + bos4_1 + bos5_1 + bos6_1boredom_2 =~ lambda0*bos1_2 + bos1_2 + bos2_2 + bos3_2 + bos4_2 + bos5_2 + bos6_2
# interceptsbos1_0 ~ i1*1
bos2_0 ~ 1bos3_0 ~ 1bos4_0 ~ 1bos5_0 ~ 1bos6_0 ~ 1
bos1_1 ~ i1*1
bos2_1 ~ 1bos3_1 ~ 1bos4_1 ~ 1bos5_1 ~ 1bos6_1 ~ 1
bos1_2 ~ i1*1
bos2_2 ~ 1bos3_2 ~ 1bos4_2 ~ 1bos5_2 ~ 1bos6_2 ~ 1# unique variances
bos1_0 ~~ bos1_0bos2_0 ~~ bos2_0bos3_0 ~~ bos3_0bos4_0 ~~ bos4_0bos5_0 ~~ bos5_0bos6_0 ~~ bos6_0bos1_1 ~~ bos1_1bos2_1 ~~ bos2_1bos3_1 ~~ bos3_1bos4_1 ~~ bos4_1bos5_1 ~~ bos5_1bos6_1 ~~ bos6_1bos1_2 ~~ bos1_2bos2_2 ~~ bos2_2bos3_2 ~~ bos3_2bos4_2 ~~ bos4_2bos5_2 ~~ bos5_2bos6_2 ~~ bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'# model estimation
fit_configural_boredom <- cfa(configural_boredom, data = df1, missing = "FIML", estimator = "MLR")summary(fit_configural_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.2 Weak Invariance ---------------------------------------------------# model specification (additional constraints on latent factors)
# same factor loadings for each item over time
weak_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2
# interceptsbos1_0 ~ i1*1
bos2_0 ~ 1bos3_0 ~ 1bos4_0 ~ 1bos5_0 ~ 1bos6_0 ~ 1
bos1_1 ~ i1*1
bos2_1 ~ 1bos3_1 ~ 1bos4_1 ~ 1bos5_1 ~ 1bos6_1 ~ 1
bos1_2 ~ i1*1
bos2_2 ~ 1bos3_2 ~ 1bos4_2 ~ 1bos5_2 ~ 1bos6_2 ~ 1
# unique variances and covariancesbos1_0 ~~ bos1_0bos2_0 ~~ bos2_0bos3_0 ~~ bos3_0bos4_0 ~~ bos4_0bos5_0 ~~ bos5_0bos6_0 ~~ bos6_0bos1_1 ~~ bos1_1bos2_1 ~~ bos2_1bos3_1 ~~ bos3_1bos4_1 ~~ bos4_1bos5_1 ~~ bos5_1bos6_1 ~~ bos6_1bos1_2 ~~ bos1_2bos2_2 ~~ bos2_2bos3_2 ~~ bos3_2bos4_2 ~~ bos4_2bos5_2 ~~ bos5_2bos6_2 ~~ bos6_2bos1_0 ~~ bos1_1 + bos1_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'# model estimation
fit_weak_boredom <- cfa(weak_boredom, data = df1, missing = "FIML", estimator = "MLR")summary(fit_weak_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.3 Strong Invariance -------------------------------------------------# model specification (additional constraints on manifest intercepts)
strong_boredom <- '# measurement modelboredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'
# model estimationfit_strong_boredom <- cfa(strong_boredom, data = df1, missing = "FIML", estimator = "MLR")summary(fit_strong_boredom, fit.measures = TRUE, standardized = TRUE)Unfortunately, if I am comparing the models now using the code from Steinmetz (2014) the first p-value is NA:# corrected chi-square differences testCorrDiff <- function(fit.baseline, fit.restricted) # basline = model with less degrees of freedom{Corrc2Base <- fitMeasures(fit.baseline)[[6]] # corrected chi-square valueMLc2Base <- fitMeasures(fit.baseline)[[3]] # uncorrected chi-square valuedfBase <- fitMeasures(fit.baseline)[[4]] # degrees of freedomCorrc2Rest <- fitMeasures(fit.restricted)[[6]]MLc2Rest <- fitMeasures(fit.restricted)[[3]]dfRest <- fitMeasures(fit.restricted)[[4]]c0 <- MLc2Rest / Corrc2Restc1 <- MLc2Base / Corrc2Basecd <- (dfRest*c0-dfBase*c1)/(dfRest-dfBase)CorrDiff <- (MLc2Rest-MLc2Base)/cd # corrected difference test statistic T_d^*dfDiff <- dfRest - dfBasepDiff <- 1-pchisq(CorrDiff, dfDiff)result <- list(Corr.chisq.difference = CorrDiff,df.difference=dfDiff, p.value=pDiff)return(result)}# model comparisonCorrDiff(fit_configural_boredom, fit_weak_boredom)CorrDiff(fit_weak_boredom, fit_strong_boredom)Warning:In pchisq(CorrDiff, dfDiff) : NaNs producedFurthermore, if I am then using the sem or growth function to calculate my growth model using the longitudinal scalar invariance model with the addition by Mauricio I get negative lv variances:
strong_boredom_growth <- '# measurement model
boredom_0 =~ lambda0*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0 + lambda6*bos6_0boredom_1 =~ lambda0*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1 + lambda6*bos6_1boredom_2 =~ lambda0*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2 + lambda6*bos6_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 0*1boredom_2 ~ 0*1# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2
boredom_0 ~~ 0*boredom_1boredom_0 ~~ 0*boredom_2boredom_1 ~~ 0*boredom_2
# adding the growth modeli =~ 1*boredom_0 + 1*boredom_1 + 1*boredom_2 # intercepts =~ 0*boredom_0 + 1*boredom_1 + 2*boredom_2 # slope
i ~ 1s ~ 1
'# model estimationfit_strong_boredom_growth <- sem(strong_boredom_growth, data=df1, missing = "FIML", estimator = "MLR")
Warning:In lav_object_post_check(object) :lavaan WARNING: some estimated lv variances are negative
Thanks,Manuelmal...@malonequantitative.com schrieb am Montag, 14. Dezember 2020 um 16:20:03 UTC+1:Manuel,Interleaved:On Mon, Dec 14, 2020 at 5:44 AM Manuel <mailsc...@gmail.com> wrote:Dear Pat,As commented in the code (in the note directly above that line of code) this is done to force this factor loading to be free. I therefore pre-multiply it with NA, as a hint to Lavaan that the value of this parameter is still unknown.I understand that, but you shouldn't need to do *both* that *and* lambda1*bos1_0 in the same measurement equation. The latter makes the former redundant.I tried the growth and sem function and attached the two outputs as pdf. Using the sem function without i ~ 1 and s ~ 1 intercept and slope would be 0.I find it a bit spooky that the results differ when using different functions. Are you certain that I can trust the results of the sem function?That's why I said you'd need to specify those for the sem() wrapper. As far as which to trust, it looks like there's a slight shift in the observed-variable handling--the intercepts all differ by .018, which is reflected in a difference of .018 in the other direction in the intercept of i. The model appears to be otherwise identical, and the fit statistics are identical. The difference appears to be an arbitrary artifact that won't affect your interpretation.PatThanks,Manuelmal...@malonequantitative.com schrieb am Freitag, 11. Dezember 2020 um 17:33:05 UTC+1:I haven't been following this thread closely, but what's the benefit of the first right-hand-side term inboredom_0 =~ NA*bos1_0 + lambda1*bos1_0 +(and similar for _1 and _2). I can't figure out what it would do, versusboredom_0 =~ lambda1*bos1_0 +Also, I'd recommend using the sem() wrapper instead of the growth() wrapper, since growth() is based on, as far as I know, growth of observed variables, not latents. You specify so much else in your model, I think sem() would work fine and be less likely to run into unintended defaults. Though you may need to add:
i ~ 1s ~ 1
PatOn Fri, Dec 11, 2020 at 11:17 AM Manuel <mailsc...@gmail.com> wrote:Unfortunately changing means to 0 still leads resulted in the error. Adding missing = "FIML" solved it though.Just to double check I am doing it right, here is my code:# 2. Define Models --------------------------------------------------------# exploring measurement invariance over timelibrary(lavaan)
# * 2.1 Configural Invariance ---------------------------------------------
# note: to force this factor loading to be free, we pre-multiply it with NA, as a hint to lavaan that the value of this parameter is still unknown.configural_boredom <- '# measurement modelboredom_0 =~ NA*bos1_0 + lambda1*bos1_0 + bos2_0 + bos3_0 + bos4_0 + bos5_0 + bos6_0boredom_1 =~ NA*bos1_1 + lambda1*bos1_1 + bos2_1 + bos3_1 + bos4_1 + bos5_1 + bos6_1boredom_2 =~ NA*bos1_2 + lambda1*bos1_2 + bos2_2 + bos3_2 + bos4_2 + bos5_2 + bos6_2
# interceptsbos1_0 ~ i1*1
bos2_0 ~ 1bos3_0 ~ 1bos4_0 ~ 1bos5_0 ~ 1bos6_0 ~ 1
bos1_1 ~ i1*1
bos2_1 ~ 1bos3_1 ~ 1bos4_1 ~ 1bos5_1 ~ 1bos6_1 ~ 1
bos1_2 ~ i1*1
bos2_2 ~ 1bos3_2 ~ 1bos4_2 ~ 1bos5_2 ~ 1bos6_2 ~ 1# unique variances
bos1_0 ~~ bos1_0bos2_0 ~~ bos2_0bos3_0 ~~ bos3_0bos4_0 ~~ bos4_0bos5_0 ~~ bos5_0bos6_0 ~~ bos6_0bos1_1 ~~ bos1_1bos2_1 ~~ bos2_1bos3_1 ~~ bos3_1bos4_1 ~~ bos4_1bos5_1 ~~ bos5_1bos6_1 ~~ bos6_1bos1_2 ~~ bos1_2bos2_2 ~~ bos2_2bos3_2 ~~ bos3_2bos4_2 ~~ bos4_2bos5_2 ~~ bos5_2bos6_2 ~~ bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'# model estimation
fit_configural_boredom <- cfa(configural_boredom, data = df1, missing = "FIML")summary(fit_configural_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.2 Weak Invariance ---------------------------------------------------
# model specification (additional constraints on latent factors)weak_boredom <- '# measurement modelboredom_0 =~ NA*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0+ lambda6*bos6_0boredom_1 =~ NA*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1+ lambda6*bos6_1boredom_2 =~ NA*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2+ lambda6*bos6_2
# interceptsbos1_0 ~ i1*1
bos2_0 ~ 1bos3_0 ~ 1bos4_0 ~ 1bos5_0 ~ 1bos6_0 ~ 1
bos1_1 ~ i1*1
bos2_1 ~ 1bos3_1 ~ 1bos4_1 ~ 1bos5_1 ~ 1bos6_1 ~ 1
bos1_2 ~ i1*1
bos2_2 ~ 1bos3_2 ~ 1bos4_2 ~ 1bos5_2 ~ 1bos6_2 ~ 1
# unique variances and covariancesbos1_0 ~~ bos1_0bos2_0 ~~ bos2_0bos3_0 ~~ bos3_0bos4_0 ~~ bos4_0bos5_0 ~~ bos5_0bos6_0 ~~ bos6_0bos1_1 ~~ bos1_1bos2_1 ~~ bos2_1bos3_1 ~~ bos3_1bos4_1 ~~ bos4_1bos5_1 ~~ bos5_1bos6_1 ~~ bos6_1bos1_2 ~~ bos1_2bos2_2 ~~ bos2_2bos3_2 ~~ bos3_2bos4_2 ~~ bos4_2bos5_2 ~~ bos5_2bos6_2 ~~ bos6_2bos1_0 ~~ bos1_1 + bos1_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'# model estimation
fit_weak_boredom <- cfa(weak_boredom, data = df1, missing = "FIML")summary(fit_weak_boredom, fit.measures = TRUE, standardized = TRUE)
# * 2.3 Strong Invariance -------------------------------------------------# model specification (additional constraints on manifest intercepts)
strong_boredom <- '# measurement modelboredom_0 =~ NA*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0+ lambda6*bos6_0boredom_1 =~ NA*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1+ lambda6*bos6_1boredom_2 =~ NA*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2+ lambda6*bos6_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2'
# model estimationfit_strong_boredom <- cfa(strong_boredom, data = df1, missing = "FIML")summary(fit_strong_boredom, fit.measures = TRUE, standardized = TRUE)# 3. Model Comparison ----------------------------------------------------# * 3.1 Steinmetz, 2014 ---------------------------------------------------# corrected chi-square differences testCorrDiff <- function(fit.baseline, fit.restricted) # basline = model with less degrees of freedom{Corrc2Base <- fitMeasures(fit.baseline)[[6]] # corrected chi-square valueMLc2Base <- fitMeasures(fit.baseline)[[3]] # uncorrected chi-square valuedfBase <- fitMeasures(fit.baseline)[[4]] # degrees of freedomCorrc2Rest <- fitMeasures(fit.restricted)[[6]]MLc2Rest <- fitMeasures(fit.restricted)[[3]]dfRest <- fitMeasures(fit.restricted)[[4]]c0 <- MLc2Rest / Corrc2Restc1 <- MLc2Base / Corrc2Basecd <- (dfRest*c0-dfBase*c1)/(dfRest-dfBase)CorrDiff <- (MLc2Rest-MLc2Base)/cd # corrected difference test statistic T_d^*dfDiff <- dfRest - dfBasepDiff <- 1-pchisq(CorrDiff, dfDiff)result <- list(Corr.chisq.difference = CorrDiff,df.difference=dfDiff, p.value=pDiff)return(result)}# model comparisonCorrDiff(fit_configural_boredom, fit_weak_boredom)CorrDiff(fit_weak_boredom, fit_strong_boredom)CorrDiff(fit_strong_boredom, fit_strict_boredom)# 3.2 PennState Alternative -----------------------------------------------# according to: https://quantdev.ssri.psu.edu/tutorials/intro-basics-longitudinal-measurement-invariance# compare model fit statisticsround(cbind(configural=inspect(fit_configural_boredom, 'fit.measures'),weak=inspect(fit_weak_boredom, 'fit.measures'),strong=inspect(fit_strong_boredom, 'fit.measures'),strict=inspect(fit_strict_boredom, 'fit.measures')),3)# chi-square difference test for nested modelsanova(fit_configural_boredom, fit_weak_boredom)anova(fit_weak_boredom, fit_strong_boredom)anova(fit_strong_boredom, fit_strict_boredom)# 4. Fitting Boredom Growth in Lavaan using Strong Invariance -------------
# model specification (first order factor means fixed to 0)strong_boredom_growth <- '# measurement model
boredom_0 =~ NA*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0+ lambda6*bos6_0boredom_1 =~ NA*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1+ lambda6*bos6_1boredom_2 =~ NA*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2+ lambda6*bos6_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 0*1boredom_2 ~ 0*1# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2
boredom_0 ~~ 0*boredom_1boredom_0 ~~ 0*boredom_2boredom_1 ~~ 0*boredom_2
# adding the growth modeli =~ 1*boredom_0 + 1*boredom_1 + 1*boredom_2 # intercepts =~ 0*boredom_0 + 1*boredom_1 + 2*boredom_2 # slope'
# model estimationfit_strong_boredom_growth <- growth(strong_boredom_growth, data=df1, missing = "FIML")summary(fit_strong_boredom_growth, fit.measures = TRUE, standardized = TRUE)# * 4.1 Adding Boredom Growth Parameters to Dataframe ---------------------
idx <- lavInspect(fit_strong_boredom_growth, "case.idx")
fscores <- lavPredict(fit_strong_boredom_growth, assemble = TRUE)
## loop over factorsfor (fs in colnames(fscores)) {df1[idx, fs] <- fscores[, fs]}
mauga...@gmail.com schrieb am Donnerstag, 10. Dezember 2020 um 11:01:00 UTC+1:ManuelChange these ines of codeYou want the first order factor means fix to 0, so the mean change is represented by the intercepte and slopeWant to have the facto relation represented by the growth curve
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 0*1boredom_2 ~ 0*1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2
boredom_0 ~~ 0*boredom_1boredom_0 ~~ 0*boredom_2boredom_1 ~~ 0*boredom_2
On Thursday, December 10, 2020 at 8:58:10 AM UTC+1 mailsc...@gmail.com wrote:
Dear Mauricio,I see. Then I misunderstood you saying I should "use the factors from the Strong invariance model for the growth curve". It also felt unusual.This is my model for longitudinal scalar invariance and I added the growth curve at the end:
strong_boredom_growth <- '# measurement model
boredom_0 =~ NA*bos1_0 + lambda1*bos1_0 + lambda2*bos2_0 + lambda3*bos3_0 + lambda4*bos4_0 + lambda5*bos5_0+ lambda6*bos6_0boredom_1 =~ NA*bos1_1 + lambda1*bos1_1 + lambda2*bos2_1 + lambda3*bos3_1 + lambda4*bos4_1 + lambda5*bos5_1+ lambda6*bos6_1boredom_2 =~ NA*bos1_2 + lambda1*bos1_2 + lambda2*bos2_2 + lambda3*bos3_2 + lambda4*bos4_2 + lambda5*bos5_2+ lambda6*bos6_2
bos2_0 ~~ bos2_1 + bos2_2
bos3_0 ~~ bos3_1 + bos3_2
bos4_0 ~~ bos4_1 + bos4_2
bos5_0 ~~ bos5_1 + bos5_2
bos6_0 ~~ bos6_1 + bos6_2
# latent variables meansboredom_0 ~ 0*1
boredom_1 ~ 1boredom_2 ~ 1
# latent variables variances and covariancesboredom_0 ~~ 1*boredom_0
boredom_1 ~~ boredom_1boredom_2 ~~ boredom_2boredom_0 ~~ boredom_1boredom_0 ~~ boredom_2boredom_1 ~~ boredom_2
# adding the growth model
i =~ 1*boredom_0 + 1*boredom_1 + 1*boredom_2 # intercepts =~ 0*boredom_0 + 1*boredom_1 + 2*boredom_2 # slope'
# model estimationboredom_growth_model = growth(strong_boredom_growth, data=df1)summary(boredom_growth_model)Unfortunately, this again results in an error:1: In lav_model_vcov(lavmodel = lavmodel, lavsamplestats = lavsamplestats, :
lavaan WARNING:The variance-covariance matrix of the estimated parameters (vcov)does not appear to be positive definite! The smallest eigenvalue
(= 1.853961e-18) is close to zero. This may be a symptom that themodel is not identified.2: In lav_object_post_check(object) :
lavaan WARNING: some estimated lv variances are negative
I looked at the summary anyways and attached it as pdf, if this is of any help.Kind regards,Manuelmauga...@gmail.com schrieb am Donnerstag, 10. Dezember 2020 um 00:49:39 UTC+1:ManuelIt is not recommended for you to add the factor scores as measured variables, and then run the growth model with them. This goes back into the porblem of factor score indeteminancy and other issues of factor score variability and method.The recommend steps would be t estimate the growth curve on top of the longitudinal scalar invariance model. This would required you to add 2 pieces to the measurement inavriance model- The intercept and slope factors define by the first order factors, as you have it- fix the first order factors means to 0. This way the mean change over time would be only define by the growth curveHope this helps
On Wednesday, December 9, 2020 at 4:54:55 PM UTC+1 mal...@malonequantitative.com wrote:
Manuel,It sounds like a different usage of "factor."What do you get from class(df1$boredom_0) ? It should be either numeric (double) or ordered, not factor. Factor in that sense would mean a nominal variable, which can't be used as an endogenous variable in lavaan. Using as.numeric will give a value for each unique value of a nominal variable.lavPredict() should be returning class numeric. I'm not sure where they're getting converted to class factor.PatOn Wed, Dec 9, 2020 at 10:43 AM Manuel <mailsc...@gmail.com> wrote:Dear Magua, dear Patrick,Thank you for your help!I have managed to establish scalar longitudinal measurement invariance for boredom and added the scalar boredom factor scores to my data frame using this code:idx <- lavInspect(fit_strong_boredom, "case.idx")fscores <- lavPredict(fit_strong_boredom, assemble = TRUE)
## loop over factorsfor (fs in colnames(fscores)) {df1[idx, fs] <- fscores[, fs]}
Now I am trying to extract the slope parameters using the boredom factor scores:boredom_growth <- '
i =~ 1*boredom_0 + 1*boredom_1 + 1*boredom_2 # intercept
s =~ 0*boredom_0 + 1*boredom_1 + 2*boredom_2 # slope'growthCurveModel = growth(boredom_growth, data=df1)But this again results in an error:Error in lav_data_full(data = data, group = group, cluster = cluster, :lavaan ERROR: unordered factor(s) detected; make them numeric or ordered: boredom_0 boredom_1 boredom_2The factor scores range from -0,000154379130794116 to 2,78171374926366. Using as.numeric(df1$boredom_0) strangely results in values from 1 to 1186.Do you have any idea how I can solve this?Thanks again,Manuelmal...@malonequantitative.com schrieb am Mittwoch, 2. Dezember 2020 um 16:40:33 UTC+1:Manuel,
I suspect you're running into issues with the factor intercepts.
I'm not sure whether the growth() function can do this, but the sem()
function could. Then if you specify scalar invariance on the boredom
factors as Mauricio mentioned, then
boredom_0 ~ 0*1
boredom_1 ~ 0*1
boredom_2 ~ 0*1
i ~ 1
s ~ 1
That should get you on the right track.
On Wed, Dec 2, 2020 at 5:07 AM Manuel <mailsc...@gmail.com> wrote:
>
> Dear Terrence,
>
> Thank you very much for your answer. It helped a lot.
>
> Is there a way to run a double latent growth model in Lavaan?
> I would like to use boredom factor scores instead of manifest boredom means. In my mind it should look like this:
>
> latent_boredom_growth <- '
> boredom_0 =~ bos1_0 + bos2_0 + bos3_0 + bos4_0 + bos5_0 + bos6_0; #latent boredom
> boredom_1 =~ bos1_1 + bos2_1 + bos3_1 + bos4_1 + bos5_1 + bos6_1;
> boredom_2 =~ bos1_2 + bos2_2 + bos3_2 + bos4_2 + bos5_2 + bos6_2;
>
> i =~ 1*boredom_0 + 1*boredom_1 + 1*boredom_2; # intercept
> s =~ 0*boredom_0 + 1*boredom_1 + 2*boredom_2; # slope
> '
> boredom_growth_model = growth(latent_boredom_growth, data=lavan)
>
> But this results in an error:
>
> In lav_model_vcov(lavmodel = lavmodel, lavsamplestats = lavsamplestats, :
> lavaan WARNING:
> Could not compute standard errors! The information matrix could
> not be inverted. This may be a symptom that the model is not
> identified.
>
> Thanks again and kind regards,
> Manuel
> Terrence Jorgensen schrieb am Freitag, 13. November 2020 um 11:59:12 UTC+1:
>>>
>>> Am I doing this right?
>>
>> Looks right.
>>>
>>> How do I interpret the output?
>>
>> https://lavaan.ugent.be/tutorial/growth.html
>> Try Googling for more tutorials about growth curves in lavaan, like this one: https://quantdev.ssri.psu.edu/tutorials/growth-modeling-chapter-10-growth-models-nonlinearity-time
>>
>>> Why are all intercepts 0?
>>
>> They aren't. Only the indicators have intercepts == 0 because their means are reproduces as functions of the growth parameters. The growth parameter means are merely very close to zero (try adding the argument nd=7 for the summary() to print up to 7 digits of precision). Slopes nearly zero seems very consistent with the dark blue line in your plot being almost flat. The plot indicates your (unconditional) average intercept should be somewhere between 2 and 3; however, you have several predictors of the growth factors. Thus, the intercepts are the mean level and change when all those predictors == 0. Does that make sense for your data?
>>>
>>> What does it mean that intercept, slope, and quadratic slope are not significant?
>>
>> It implies those parameters are consistent with a population parameter == 0.
>>
>> Terrence D. Jorgensen
>> Assistant Professor, Methods and Statistics
>> Research Institute for Child Development and Education, the University of Amsterdam
>> http://www.uva.nl/profile/t.d.jorgensen
>>
>
> --
> 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/2ac441be-e959-4a3b-b72e-f72997d94bebn%40googlegroups.com.
--
Patrick S. Malone, Ph.D., Malone Quantitative
NEW Service Models: http://malonequantitative.com
He/Him/His
--
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/5f9bb835-84c4-4390-b659-33e6fef4d105n%40googlegroups.com.
--Patrick S. Malone, Ph.D., Malone Quantitative
NEW Service Models: http://malonequantitative.com
He/Him/His
--
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/8c2bc5a4-e34e-4526-a29b-0b662e94b644n%40googlegroups.com.
--Patrick S. Malone, Ph.D., Malone Quantitative
NEW Service Models: http://malonequantitative.com
He/Him/His
--
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/8668c7e6-8035-4d1d-8d8e-13034d1d61cbn%40googlegroups.com.