version 13 capture log off /* Author: Sven Oliver Spiess, Dittrich & Partner Consulting (DPC) GmbH Date: Jun 22, 2018 Purpose: Provide an illustrative example for talk on longitudinal null models at 2018 German Stata User Group Meeting, Konstanz Require: Stata 13 or above, internet connection Note: This is no real-life, substantive application but a general example using publicly available data to illustrate the underlying 'mechanics' of the proposed approach in Stata; interpret results with care! */ clear use http://www.stata-press.com/data/r15/sem_sm2.dta // [SEM] manual data set from example 9 in Stata 15 // type -view mansection SEM example9- for details *1. Estimate Longitudinal Target Model: *====================================== sem /// (anomia67 pwless67 <- Alien67) /// measurement piece (anomia71 pwless71 <- Alien71) /// measurement piece (Alien71 <- Alien67) // structural piece estat gof, stat(indices) global cfi_db = r(cfi) global tli_db = r(tli) estimates store model local suffix "m" global chi2_`suffix' = e(chi2_ms) global df_`suffix' = e(df_ms) global diff_`suffix' = ${chi2_`suffix'} - ${df_`suffix'} *2. Reproduce Default Baseline/Null Model: *========================================= // assumptions: // - no latent constructs // - no covariances among manifest variables (implies all variables exogenous) // type -help sem and gsem option covstructure- for details sem /// (anomia67 anomia71 pwless67 pwless71) /// observed variables only , covstruct(_Ex, diagonal) estimates store default_baseline local suffix "db" global chi2_`suffix' = e(chi2_ms) global df_`suffix' = e(df_ms) global diff_`suffix' = ${chi2_`suffix'} - ${df_`suffix'} *3. Compare Fit Indices from Automatic versus Reproduced Baseline: *================================================================= **Compute fit indices from reproduced model (2.) above: **----------------------------------------------------- //type -view mansection SEM methodsandformulasforsem- for details qui{ noi: di "{txt}{ul:Formulas for fit indices:}" _n noi: di "{txt} (chi2_ms - df_ms)" _n /// "CFI = 1 - {dup 45:{c -}}" _n /// " max((chi2_ms - df_ms), (chi2_{it:base} - df_{it:base}))" _n(2) noi: di "{txt} (chi2_{it:base}/df_{it:base}) - (chi2_ms/df_ms)" _n /// "TLI = {dup 37:{c -}}" _n /// " (chi2_{it:base}/df_{it:base}) - 1" _n(4) noi: di "{txt}{ul:Fit indices with reproduced null-/baseline-model:}" _n noi: di "{txt}CFI = 1 - [max(({res}" %6.3f $chi2_m "{txt} - {res}" %1.0f $df_m "){txt}, {res}0{txt}) /" _n /// " max(({res}" %6.3f $chi2_m "{txt} - {res}" %1.0f $df_m "){txt}, ({res}" %8.3f $chi2_db "{txt} - {res}" %1.0f $df_db "){txt}, {res}0{txt})]" _n /// " = {res}" 1 - [max($diff_m, 0) / max($diff_m, $diff_db, 0) ] _n noi: di "{txt}TLI = (({res}" %8.3f $chi2_db "{txt}/{res}" %1.0f $df_db "{txt}) - ({res}" %6.3f $chi2_m "{txt}/{res}" %1.0f $df_m "{txt})) / " /// "{txt}(({res}" %8.3f $chi2_db "{txt}/{res}" %1.0f $df_db "{txt}) - {res}1{txt})" _n /// " = {res}" (($chi2_db/$df_db) - ($chi2_m/$df_m)) / (($chi2_db/$df_db) - 1) _n noi: di _n "{txt}(Note: {cmd}estat gof {txt}results: CFI = {res}" $cfi_db "{txt}; TLI = {res}" $tli_db "{txt})" } **Compare results and assert identical: **------------------------------------- assert 1 - [max($diff_m, 0) / max($diff_m, $diff_db, 0) ] == $cfi_db assert (($chi2_db/$df_db) - ($chi2_m/$df_m)) / (($chi2_db/$df_db) - 1) == $tli_db *4. Estimate Longitudinal Baseline: (e.g., sensu Little, et al.) *================================== // restrictions of equal means & variances across time points imposed in // -mean()- and -var()- options, respectively sem /// (anomia67 anomia71 pwless67 pwless71) /// measurement piece , covstruct(_Ex, diagonal) /// mean( /// constrain corresponding means to equality anomia67@m1 anomia71@m1 /// pwless67@m2 pwless71@m2 /// ) /// var( /// constrain corresponding variances to equality anomia67@v1 anomia71@v1 /// pwless67@v2 pwless71@v2 /// ) /// estimates store longitudinal_baseline local suffix "lb" global chi2_`suffix' = e(chi2_ms) global df_`suffix' = e(df_ms) global diff_`suffix' = ${chi2_`suffix'} - ${df_`suffix'} *5. Compare Default vs. Longitudinal Baselines: *============================================== qui{ noi: di "{txt}{ul:Fit with longitudinal baseline-model:}" _n noi: di "{txt}CFI = 1 - [max(({res}" %6.3f $chi2_m "{txt} - {res}" %1.0f $df_m "){txt}, {res}0{txt}) /" _n /// " max(({res}" %6.3f $chi2_m "{txt} - {res}" %1.0f $df_m "){txt}, ({res}" %8.3f $chi2_lb "{txt} - {res}" %1.0f $df_lb "){txt}, {res}0{txt})]" _n /// " = {res}" 1 - [max($diff_m, 0) / max($diff_m, $diff_lb, 0) ] _n noi: di "{txt}TLI = (({res}" %8.3f $chi2_lb "{txt}/{res}" %1.0f $df_lb "{txt}) - ({res}" %6.3f $chi2_m "{txt}/{res}" %1.0f $df_m "{txt})) / " /// "{txt}(({res}" %8.3f $chi2_lb "{txt}/{res}" %1.0f $df_lb "{txt}) - {res}1{txt})" _n /// " = {res}" (($chi2_lb/$df_lb) - ($chi2_m/$df_m)) / (($chi2_lb/$df_lb) - 1) _n noi: di _n "{txt}(Note: {cmd}estat gof {txt}results: CFI = {res}" $cfi_db "{txt}; TLI = {res}" $tli_db "{txt})" } exit