Comparing One- and Two-Profile Models
Ivan Jacob Agaloos Pesigan
Source:vignettes/sim-culta-1-profile.Rmd
sim-culta-1-profile.Rmd
We generate data using the CULTA model with two latent profiles, where profile membership depends on a covariate and profile transitions follow a multinomial structure. However, for model fitting, we impose a simpler structure by fitting a CUTS (1 Profile) model with autoregressive effects, ignoring the latent profiles during estimation. We then compare this misspecified model to the correctly specified two-profile CULTA model.
Data Generation
# complete list of R function arguments
# random seed for reproducibility
set.seed(42)
# dimensions
n # number of individuals
#> [1] 10000
m # measurement occasions
#> [1] 6
p # number of items
#> [1] 4
q # common trait dimension
#> [1] 1
# covariate parameters
mu_x
#> [1] 11.4009
sigma_x
#> [1] 24.67566
# profile membership and transition parameters
nu_0
#> [1] -3.563
kappa_0
#> [1] 0.122
alpha_0
#> [1] -3.586
beta_00
#> [1] 2.25
gamma_00
#> [1] 0.063
gamma_10
#> [1] 0.094
# trait parameters
psi_t
#> [,1]
#> [1,] 0.1
mu_t
#> [1] 0
psi_p
#> [,1] [,2] [,3] [,4]
#> [1,] 0.1 0.0 0.0 0.0
#> [2,] 0.0 0.1 0.0 0.0
#> [3,] 0.0 0.0 0.5 0.0
#> [4,] 0.0 0.0 0.0 0.5
mu_p
#> [1] 0 0 0 0
common_trait_loading
#> [,1]
#> [1,] 1
#> [2,] 1
#> [3,] 1
#> [4,] 1
# state parameters
common_state_loading
#> [,1]
#> [1,] 1
#> [2,] 1
#> [3,] 1
#> [4,] 1
phi_0
#> [1] 0
phi_1
#> [1] 0.311
psi_s0
#> [1] 1
psi_s
#> [1] 0.25
theta
#> [,1] [,2] [,3] [,4]
#> [1,] 0.15 0.00 0.00 0.00
#> [2,] 0.00 0.15 0.00 0.00
#> [3,] 0.00 0.00 0.15 0.00
#> [4,] 0.00 0.00 0.00 0.15
# profile-specific means
mu_profile
#> [,1] [,2]
#> [1,] 2.253 -0.278
#> [2,] 1.493 -0.165
#> [3,] 1.574 -0.199
#> [4,] 1.117 -0.148
data <- GenCULTA2Profiles(
n = n,
m = m,
mu_x = mu_x,
sigma_x = sigma_x,
nu_0 = nu_0,
kappa_0 = kappa_0,
alpha_0 = alpha_0,
beta_00 = beta_00,
gamma_00 = gamma_00,
gamma_10 = gamma_10,
mu_t = mu_t,
psi_t = psi_t,
mu_p = mu_p,
psi_p = psi_p,
common_trait_loading = common_trait_loading,
common_state_loading = common_state_loading,
phi_0 = phi_0,
phi_1 = phi_1,
psi_s0 = psi_s0,
psi_s = psi_s,
theta = theta,
mu_profile = mu_profile
)
Model Fitting
The FitCULTA1Profiles
function fits the misspecified
one-profile model using Mplus
. Note: This
function requires that Mplus is already installed on
the system.
one_profile <- FitCULTA1Profile(data = data)
The FitCULTA2Profiles
function fits the correct
two-profile model using Mplus
. Note: This
function requires that Mplus is already installed on
the system. To speed up model fitting, consider using the
ncores
argument to leverage multiple cores.
two_profiles <- FitCULTA2Profiles(data = data)
Model Comparison
The anova
function can be used to compare the two fitted
models.
anova(one_profile, two_profiles)
#> $fit
#> logLik df correction AIC BIC aBIC entropy
#> 1-profile CULTA -246042.9 22 1.083395 492129.8 492288.5 492218.5 0.0000000
#> 2-profile CULTA -237508.2 33 1.000768 475082.4 475320.3 475215.5 0.9367669
#>
#> $test
#> chi_diff df_diff p_value
#> 20429.88 11.00 0.00
Mplus Script Used
The one-profile model was estimated using the following
Mplus
script.
TITLE:
CUTS with AR;
DATA:
FILE = cutsar_data.dat;
VARIABLE:
NAMES =
id
x
y1t0
y2t0
y3t0
y4t0
y1t1
y2t1
y3t1
y4t1
y1t2
y2t2
y3t2
y4t2
y1t3
y2t3
y3t3
y4t3
y1t4
y2t4
y3t4
y4t4
y1t5
y2t5
y3t5
y4t5
;
USEVARIABLES =
y1t0
y2t0
y3t0
y4t0
y1t1
y2t1
y3t1
y4t1
y1t2
y2t2
y3t2
y4t2
y1t3
y2t3
y3t3
y4t3
y1t4
y2t4
y3t4
y4t4
y1t5
y2t5
y3t5
y4t5
;
ANALYSIS:
TYPE = GENERAL;
ESTIMATOR = MLR;
STARTS = 10;
MODEL = NOCOV;
MODEL:
! common trait ------------------------------------------------------
!! factor loadings
!!! t = 0
t BY y1t0@1;
t BY y2t0 (lambdat2);
t BY y3t0 (lambdat3);
t BY y4t0 (lambdat4);
!!! t = 1
t BY y1t1@1;
t BY y2t1 (lambdat2);
t BY y3t1 (lambdat3);
t BY y4t1 (lambdat4);
!!! t = 2
t BY y1t2@1;
t BY y2t2 (lambdat2);
t BY y3t2 (lambdat3);
t BY y4t2 (lambdat4);
!!! t = 3
t BY y1t3@1;
t BY y2t3 (lambdat2);
t BY y3t3 (lambdat3);
t BY y4t3 (lambdat4);
!!! t = 4
t BY y1t4@1;
t BY y2t4 (lambdat2);
t BY y3t4 (lambdat3);
t BY y4t4 (lambdat4);
!!! t = 5
t BY y1t5@1;
t BY y2t5 (lambdat2);
t BY y3t5 (lambdat3);
t BY y4t5 (lambdat4);
!! latent mean
[ t@0 ];
!! latent variance
t (psit);
! unique traits -----------------------------------------------------
!! factor loadings
!!! k = 1
u1 BY y1t0@1;
u1 BY y1t1@1;
u1 BY y1t2@1;
u1 BY y1t3@1;
u1 BY y1t4@1;
u1 BY y1t5@1;
!!! k = 2
u2 BY y2t0@1;
u2 BY y2t1@1;
u2 BY y2t2@1;
u2 BY y2t3@1;
u2 BY y2t4@1;
u2 BY y2t5@1;
!!! k = 3
u3 BY y3t0@1;
u3 BY y3t1@1;
u3 BY y3t2@1;
u3 BY y3t3@1;
u3 BY y3t4@1;
u3 BY y3t5@1;
!!! k = 4
u4 BY y4t0@1;
u4 BY y4t1@1;
u4 BY y4t2@1;
u4 BY y4t3@1;
u4 BY y4t4@1;
u4 BY y4t5@1;
!! latent means
[ u1@0 ];
[ u2@0 ];
[ u3@0 ];
[ u4@0 ];
!! latent variances
u1 (psip1);
u2 (psip2);
u3 (psip3);
u4 (psip4);
! common states -----------------------------------------------------
!! factor loadings
!!! t = 0
s0 BY y1t0@1;
s0 BY y2t0 (lambdas2);
s0 BY y3t0 (lambdas3);
s0 BY y4t0 (lambdas4);
!!! t = 1
s1 BY y1t1@1;
s1 BY y2t1 (lambdas2);
s1 BY y3t1 (lambdas3);
s1 BY y4t1 (lambdas4);
!!! t = 2
s2 BY y1t2@1;
s2 BY y2t2 (lambdas2);
s2 BY y3t2 (lambdas3);
s2 BY y4t2 (lambdas4);
!!! t = 3
s3 BY y1t3@1;
s3 BY y2t3 (lambdas2);
s3 BY y3t3 (lambdas3);
s3 BY y4t3 (lambdas4);
!!! t = 4
s4 BY y1t4@1;
s4 BY y2t4 (lambdas2);
s4 BY y3t4 (lambdas3);
s4 BY y4t4 (lambdas4);
!!! t = 5
s5 BY y1t5@1;
s5 BY y2t5 (lambdas2);
s5 BY y3t5 (lambdas3);
s5 BY y4t5 (lambdas4);
!! latent means
[ s0@0 ];
[ s1@0 ];
[ s2@0 ];
[ s3@0 ];
[ s4@0 ];
[ s5@0 ];
!! latent variance of s0
s0 (psis0);
!! variance of the process noise
s1 (psis);
s2 (psis);
s3 (psis);
s4 (psis);
s5 (psis);
! unique states -----------------------------------------------------
!! variances
!!! t = 0
y1t0 (theta11);
y2t0 (theta22);
y3t0 (theta33);
y4t0 (theta44);
!!! t = 1
y1t1 (theta11);
y2t1 (theta22);
y3t1 (theta33);
y4t1 (theta44);
!!! t = 2
y1t2 (theta11);
y2t2 (theta22);
y3t2 (theta33);
y4t2 (theta44);
!!! t = 3
y1t3 (theta11);
y2t3 (theta22);
y3t3 (theta33);
y4t3 (theta44);
!!! t = 4
y1t4 (theta11);
y2t4 (theta22);
y3t4 (theta33);
y4t4 (theta44);
!!! t = 5
y1t5 (theta11);
y2t5 (theta22);
y3t5 (theta33);
y4t5 (theta44);
! grand means -------------------------------------------------------
!! t = 0
[ y1t0 ] (mu1);
[ y2t0 ] (mu2);
[ y3t0 ] (mu3);
[ y4t0 ] (mu4);
!! t = 1
[ y1t1 ] (mu1);
[ y2t1 ] (mu2);
[ y3t1 ] (mu3);
[ y4t1 ] (mu4);
!! t = 2
[ y1t2 ] (mu1);
[ y2t2 ] (mu2);
[ y3t2 ] (mu3);
[ y4t2 ] (mu4);
!! t = 3
[ y1t3 ] (mu1);
[ y2t3 ] (mu2);
[ y3t3 ] (mu3);
[ y4t3 ] (mu4);
!! t = 4
[ y1t4 ] (mu1);
[ y2t4 ] (mu2);
[ y3t4 ] (mu3);
[ y4t4 ] (mu4);
!! t = 5
[ y1t5 ] (mu1);
[ y2t5 ] (mu2);
[ y3t5 ] (mu3);
[ y4t5 ] (mu4);
! inertia -----------------------------------------------------------
s0 ON s1 (phi);
s1 ON s2 (phi);
s2 ON s3 (phi);
s3 ON s4 (phi);
s4 ON s5 (phi);
MODEL CONSTRAINT:
! variance constraints
psit > 0;
psip1 > 0;
psip2 > 0;
psip3 > 0;
psip4 > 0;
psis0 > 0;
psis > 0;
theta11 > 0;
theta22 > 0;
theta33 > 0;
theta44 > 0;
OUTPUT:
TECH1
TECH3
TECH4;
SAVEDATA:
ESTIMATES = cutsar_TBpjfDc7G4UC5Z7eY3PN_estimates.dat;
RESULTS = cutsar_TBpjfDc7G4UC5Z7eY3PN_results.dat;
TECH3 = cutsar_TBpjfDc7G4UC5Z7eY3PN_tech3.dat;
TECH4 = cutsar_TBpjfDc7G4UC5Z7eY3PN_tech4.dat;