library(janitor) dfwide_OpenMx <- dfwide_OpenMx %>% clean_names() require(OpenMx) ?MxFitFunction fitFunction <- mxFitFunctionML(rowDiagnostics=TRUE) mxOption(NULL,"Default optimizer","SLSQP") ### to avoid msg error: https://openmx.ssri.psu.edu/node/4238 ################ Following Berlin, Parra & Williams (2014) model building steps, we start with Life Satisf # Prior to specifying the GMM, we need to understand the best function fitting our data. # We are gonna estimate the following models to identify # the best single-group model that will serve as the base model for the mixture analyses: # Intercept, linear, quadratic, cubic, piecewise quadratic, and latent basis no_gm_lifesatisf <- mxModel('No Growth, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'),latentVars= "eta_1", # variance paths mxPath(from=c('eta_1','life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=c(80,60,60,60,60,60,60,60,60), labels=c('psi_11', 'th', 'th', 'th', 'th', 'th', 'th', 'th','th')), # factor loadings mxPath(from='eta_1',to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), # means and intercepts mxPath(from='one', to='eta_1', arrows=1, free=TRUE, values=40, labels='alpha_1') )# close model no_gm_lifesatisf = mxModel(no_gm_lifesatisf, mxCI(c("psi_11", "th", "alpha_1"))) # list the things you want CIs for. no_gm_lifesatisf = mxRun(no_gm_lifesatisf, intervals= T) summary(no_gm_lifesatisf) summary(no_gm_lifesatisf, refModels=mxRefModels(no_gm_lifesatisf, run = TRUE)) mxTryHard_nogm_lifesatisf <- mxTryHard(no_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_nogm_lifesatisf) summary(mxTryHard_nogm_lifesatisf, refModels=mxRefModels(mxTryHard_nogm_lifesatisf, run = TRUE)) #### Script 3.10. OpenMx Script for the Linear Growth Model linear_gm_lifesatisf <- mxModel('Linear Growth, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2'), # residual variance paths mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='th'), # latent variable variances and covariance paths mxPath(from=c('eta_1','eta_2'), arrows=2, connect='unique.pairs', free=TRUE, values=c(1,0.5,1), labels=c('psi_11','psi_21','psi_22')), # factor loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(0, 1, 2, 3, 4, 5, 6, 7)), # means and intercepts mxPath(from='one', to=c('eta_1','eta_2'), arrows=1, free=TRUE, values=c(1,1), labels=c( 'alpha_1', 'alpha_2')) ) # close model linear_gm_lifesatisf = mxModel(linear_gm_lifesatisf , mxCI(c('psi_11','psi_21','psi_22', "th", "alpha_1", "alpha_2"))) # list the things you want CIs for. linear_gm_lifesatisf = mxRun(linear_gm_lifesatisf , intervals= T) summary(linear_gm_lifesatisf , refModels=mxRefModels(linear_gm_lifesatisf , run = TRUE)) mxTryHard_linear_gm_lifesatisf <- mxTryHard(linear_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_linear_gm_lifesatisf) summary(mxTryHard_linear_gm_lifesatisf, refModels=mxRefModels(mxTryHard_linear_gm_lifesatisf, run = TRUE)) # Linear growth models are an appropriate starting place for any study of individual change. # In many cases, these models are able to capture the observed change process well; however, # there are numerous times when this is not the case. Thus, it's always useful to fit and # compare additional models and consider group differences # in change. ##### from the results obtained so far, these models do not adequately represent our data... ### let's model nonlinearity quadratic_gm_lifesatisf <- mxModel('Quadratic Growth Model, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2','eta_3'), # residual variances mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='theta'), # latent variable variances & covariances mxPath(from=c('eta_1','eta_2','eta_3'), connect='unique.pairs', arrows=2, free=TRUE, values=c(1,0,0,1,0,1), labels=c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33')), # factor loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(-3, -2, -1, 0, 1, 2, 3, 4)), mxPath(from='eta_3', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(9, 4, 1, 0, 1, 4, 9, 16)), # latent variable means mxPath(from='one', to=c('eta_1','eta_2','eta_3'), arrows=1, free=TRUE, values=c(1,1,1), labels=c('alpha_1','alpha_2','alpha_3')) ) # Close Model quadratic_gm_lifesatisf = mxModel(quadratic_gm_lifesatisf, mxCI(c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33', "theta", 'alpha_1','alpha_2','alpha_3'))) # list the things you want CIs for. quadratic_gm_lifesatisf = mxRun(quadratic_gm_lifesatisf, intervals= T) ##### Warning message: In model 'Quadratic Growth Model, Path Specification' ##### Optimizer returned a non-zero status code 10. Starting values are not feasible. ##### Consider mxTryHard() mxTryHard_quadratic_gm_lifesatisf <- mxTryHard(quadratic_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_quadratic_gm_lifesatisf , refModels=mxRefModels(mxTryHard_quadratic_gm_lifesatisf , run = TRUE)) ######################################################## ######## Piecewise Quadratic Growth Model (Linear + Quadratic) piecewise_quadratic_gm_lifesatisf <- mxModel('Piecewise Quadratic Growth Model, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2','eta_3'), # residual variances mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='theta'), # latent variable variances & covariances mxPath(from=c('eta_1','eta_2','eta_3'), connect='unique.pairs', arrows=2, free=TRUE, values=c(1,0,0,1,0,1), labels=c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33')), # factor loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(0, 1, 2, 3, 4, 5, 6, 7)), mxPath(from='eta_3', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(0, 0, 0, 0, 1, 4, 9, 16)), # latent variable means mxPath(from='one', to=c('eta_1','eta_2','eta_3'), arrows=1, free=TRUE, values=c(1,1,1), labels=c('alpha_1','alpha_2','alpha_3')) ) # Close Model piecewise_quadratic_gm_lifesatisf = mxModel(piecewise_quadratic_gm_lifesatisf, mxCI(c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33', "theta", 'alpha_1','alpha_2','alpha_3'))) # list the things you want CIs for. piecewise_quadratic_gm_lifesatisf = mxRun(piecewise_quadratic_gm_lifesatisf, intervals= T) mxTryHard_piecewise_quadratic_gm_lifesatisf <- mxTryHard(piecewise_quadratic_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_bil_spline_gm_lifesatisf , refModels=mxRefModels(mxTryHard_bil_spline_gm_lifesatisf , run = TRUE)) ######## Piecewise Quadratic Growth Model: quadratic + quadratic splines piecewise_quadratic2_gm_lifesatisf <- mxModel('Piecewise Quadratic 2 Growth Model, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2','eta_3'), # residual variances mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='theta'), # latent variable variances & covariances mxPath(from=c('eta_1','eta_2','eta_3'), connect='unique.pairs', arrows=2, free=TRUE, values=c(1,0,0,1,0,1), labels=c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33')), # factor loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(0, 1, 4, 9, 16, 25, 36, 49)), mxPath(from='eta_3', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(0, 0, 0, 0, 1, 4, 9, 16)), # latent variable means mxPath(from='one', to=c('eta_1','eta_2','eta_3'), arrows=1, free=TRUE, values=c(1,1,1), labels=c('alpha_1','alpha_2','alpha_3')) ) # Close Model piecewise_quadratic2_gm_lifesatisf = mxModel(piecewise_quadratic2_gm_lifesatisf, mxCI(c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33', "theta", 'alpha_1','alpha_2','alpha_3'))) # list the things you want CIs for. piecewise_quadratic2_gm_lifesatisf = mxRun(piecewise_quadratic2_gm_lifesatisf, intervals= T) mxTryHard_piecewise_quadratic2_gm_lifesatisf <- mxTryHard(piecewise_quadratic2_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_piecewise_quadratic2_gm_lifesatisf , refModels=mxRefModels(mxTryHard_piecewise_quadratic2_gm_lifesatisf , run = TRUE)) ######################################################## ###### CUBIC cubic_gm_lifesatisf <- mxModel('Cubic Growth Model, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2','eta_3'), # residual variances mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='theta'), # latent variable variances & covariances mxPath(from=c('eta_1','eta_2','eta_3'), connect='unique.pairs', arrows=2, free=TRUE, values=c(1,0,0,1,0,1), labels=c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33')), # factor loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(-3, -2, -1, 0, 1, 2, 3, 4)), mxPath(from='eta_3', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=c(27, 8, 1, 0, 1, 8, 27, 64)), # latent variable means mxPath(from='one', to=c('eta_1','eta_2','eta_3'), arrows=1, free=TRUE, values=c(1,1,1), labels=c('alpha_1','alpha_2','alpha_3')) ) # Close Model cubic_gm_lifesatisf = mxModel(cubic_gm_lifesatisf, mxCI(c('psi_11','psi_21','psi_31','psi_22','psi_32','psi_33', "theta", 'alpha_1','alpha_2','alpha_3'))) # list the things you want CIs for. cubic_gm_lifesatisf = mxRun(cubic_gm_lifesatisf, intervals= T) ##### Warning message: In model 'Cubic Growth Model, Path Specification' ##### Optimizer returned a non-zero status code 10. Starting values are not feasible. ##### Consider mxTryHard() mxTryHard_cubic_gm_lifesatisf <- mxTryHard(cubic_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_cubic_gm_lifesatisf, refModels=mxRefModels(mxTryHard_cubic_gm_lifesatisf, run = TRUE)) ######### problem in running a cubic model.... ##### Retry limit reached; solution not found. Best fit=198393.92 (started at NA) (11 attempt(s): 4 valid, 7 errors) ############################## Script 11.10. OpenMx Script for the Latent Basis Growth Model latent_basis_gm_lifesatisf <- mxModel('Latent Basis Growth Model, Path Specification', fitFunction, type='RAM', mxData(observed=dfwide_OpenMx, type='raw'), manifestVars=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), latentVars=c('eta_1','eta_2'), # Residual Variances mxPath(from=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=2, free=TRUE, values=1, labels='theta'), # Latent Variable Covariances mxPath(from=c('eta_1','eta_2'), connect='unique.pairs', arrows=2, free=TRUE, values=c(1,0,1), labels=c('psi_11','psi_21','psi_22')), # Factor Loadings mxPath(from='eta_1', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=FALSE, values=1), mxPath(from='eta_2', to=c('life_satisf_2','life_satisf_3','life_satisf_4','life_satisf_5','life_satisf_6','life_satisf_7','life_satisf_8','life_satisf_9'), arrows=1, free=c(FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE), values=c(0,.2,.3,.4,.5,.6,.7,1), labels=c(NA,'L22','L32','L42','L52','L62','L72',NA)), # Latent Variable Means mxPath(from='one', to=c('eta_1','eta_2'), arrows=1, free=TRUE, values=c(5,5), labels=c('alpha_1','alpha_2')) ) # Close Model latent_basis_gm_lifesatisf = mxModel(latent_basis_gm_lifesatisf, mxCI(c('psi_11','psi_21','psi_22', "theta", 'alpha_1','alpha_2'))) # list the things you want CIs for. latent_basis_gm_lifesatisf = mxRun(latent_basis_gm_lifesatisf, intervals= T) mxTryHard_latentbasis_gm_lifesatisf <- mxTryHard(latent_basis_gm_lifesatisf) # Run the model, returning the result into model summary(mxTryHard_latentbasis_gm_lifesatisf, refModels=mxRefModels(mxTryHard_latentbasis_gm_lifesatisf, run = TRUE))