Here we show an example of a random intercept cross-lagged panel
model with a within \(\times\) within
interaction effect. The example below is based on Testing
for Within \(\times\) Within and
Between \(\times\) Within
Moderation Using Random Intercept Cross-Lagged Panel Models. In
particular, it is based on Section 8.4. Within \(\times\) Within Interaction Using the
Within-Person Component of a Time-Varying Moderator, and the
corresponding Mplus output files on OSF. In the original article, the Bayes
estimator was used, but here we use LMS. The LMS approach in
Mplus integrates along four dimensions, making estimation quite
impractical for this model. The LMS estimator in modsem,
however, only has to integrate along two dimensions, making estimation
viable.
library(mvtnorm)
set.seed(235910)
N <- 10000
# Simulate between-person random intercepts
phi <- matrix(c(
0.806, 0.481, 0.438,
0.481, 0.758, 0.469,
0.438, 0.469, 1.290
), nrow = 3, byrow = TRUE)
Xi <- rmvnorm(
N,
mean = c(0, 0, 0),
sigma = phi
)
RIemo <- Xi[, 1]
RIper <- Xi[, 2]
RIcon <- Xi[, 3]
# Time 3
psi3 <- matrix(c(
1.234, 0.328, 0.478,
0.328, 1.614, 0.427,
0.478, 0.427, 2.743
), nrow = 3, byrow = TRUE)
zeta3 <- rmvnorm(
N,
mean = c(0, 0, 0),
sigma = psi3
)
wemo_3 <- zeta3[, 1]
wper_3 <- zeta3[, 2]
wcon_3 <- zeta3[, 3]
# Time 5
psi5 <- matrix(c(
1.489, 0.397, 0.301,
0.397, 1.143, 0.202,
0.301, 0.202, 0.764
), nrow = 3, byrow = TRUE)
zeta5 <- rmvnorm(
N,
mean = c(0, 0, 0),
sigma = psi5
)
wemo_5 <- 0.142 * wemo_3 + 0.071 * wper_3 + 0.086 * wcon_3 - 0.010 * (wcon_3 * wper_3) + zeta5[,1]
wper_5 <- 0.018 * wemo_3 + 0.100 * wper_3 + 0.050 * wcon_3 + zeta5[,2]
wcon_5 <- -0.008 * wemo_3 + 0.006 * wper_3 + 0.105 * wcon_3 + zeta5[,3]
# Time 7
psi7 <- matrix(c(
1.808, 0.521, 0.475,
0.521, 1.287, 0.311,
0.475, 0.311, 0.881
), nrow = 3, byrow = TRUE)
zeta7 <- rmvnorm(
N,
mean = c(0, 0, 0),
sigma = psi7
)
wemo_7 <- 0.361 * wemo_5 + 0.097 * wper_5 + 0.147 * wcon_5 + 0.105 * (wcon_5 * wper_5) + zeta7[,1]
wper_7 <- 0.030 * wemo_5 + 0.348 * wper_5 + 0.123 * wcon_5 + zeta7[,2]
wcon_7 <- 0.074 * wemo_5 + 0.056 * wper_5 + 0.086 * wcon_5 + zeta7[,3]
# Indicators/Observed Variables
data <- data.frame(
emo_3 = 1.385 + RIemo + wemo_3 + rnorm(N, 0, sqrt(.200)),
emo_5 = 1.407 + RIemo + wemo_5 + rnorm(N, 0, sqrt(.200)),
emo_7 = 1.528 + RIemo + wemo_7 + rnorm(N, 0, sqrt(.200)),
per_3 = 1.563 + RIper + wper_3 + rnorm(N, 0, sqrt(.200)),
per_5 = 1.176 + RIper + wper_5 + rnorm(N, 0, sqrt(.200)),
per_7 = 1.242 + RIper + wper_7 + rnorm(N, 0, sqrt(.200)),
con_3 = 2.827 + RIcon + wcon_3 + rnorm(N, 0, sqrt(.200)),
con_5 = 1.517 + RIcon + wcon_5 + rnorm(N, 0, sqrt(.200)),
con_7 = 1.402 + RIcon + wcon_7 + rnorm(N, 0, sqrt(.200))
)model.inp <- '
# Create between components (random intercepts)
RIemo =~ 1 * emo_3 + 1 * emo_5 + 1 * emo_7;
RIcon =~ 1 * con_3 + 1 * con_5 + 1 * con_7;
# Create within-person centered variables
wemo_3 =~ 1 * emo_3;
wemo_5 =~ 1 * emo_5;
wemo_7 =~ 1 * emo_7;
wcon_3 =~ 1 * con_3;
wcon_5 =~ 1 * con_5;
wcon_7 =~ 1 * con_7;
# Moderator also needs to be decomposed into within and between parts
RIper =~ 1 * per_3 + 1 * per_5 + 1 * per_7;
wper_3 =~ 1 * per_3;
wper_5 =~ 1 * per_5;
wper_7 =~ 1 * per_7;
# Constrain the measurement error variances close to zero
# to allow for reasonable imputation times
con_3 ~~ 0.2 * con_3
con_5 ~~ 0.2 * con_5
con_7 ~~ 0.2 * con_7
emo_3 ~~ 0.2 * emo_3
emo_5 ~~ 0.2 * emo_5
emo_7 ~~ 0.2 * emo_7
per_3 ~~ 0.2 * per_3
per_5 ~~ 0.2 * per_5
per_7 ~~ 0.2 * per_7
# Estimate the covariance between the random intercepts
RIemo ~~ RIper
RIemo ~~ RIcon
RIper ~~ RIcon
# Estimate the lagged effects between
# the within-person centered variables
wemo_7 ~ wemo_5 + wper_5 + wcon_5
wper_7 ~ wemo_5 + wper_5 + wcon_5
wcon_7 ~ wemo_5 + wper_5 + wcon_5
wemo_5 ~ wemo_3 + wper_3 + wcon_3
wper_5 ~ wemo_3 + wper_3 + wcon_3
wcon_5 ~ wemo_3 + wper_3 + wcon_3
# Specify interaction terms between within-person centred
# conduct problems and the within-person centered peer problems
# predict within-person centred emotional problems with interaction
wemo_7 ~ wcon_5:wper_5
wemo_5 ~ wcon_3:wper_3
# Estimate the covariance between the within-person
# components at the first wave
wemo_3 ~~ wper_3
wemo_3 ~~ wcon_3
wper_3 ~~ wcon_3
# Estimate the covariances between the residuals of
# the within-person components (the innovations)
wemo_5 ~~ wper_5
wemo_5 ~~ wcon_5
wper_5 ~~ wcon_5
wemo_7 ~~ wper_7
wemo_7 ~~ wcon_7
wper_7 ~~ wcon_7
'
fit.lms <- modsem(
model.syntax = model.inp,
data = data,
method = "lms",
nodes = 32,
optimize = FALSE, # we're currently unable to optimize starting parameters here
orthogonal.x = TRUE, # make sure the model is identifiable
orthogonal.y = TRUE, # not strictly necessary for this model in particular
auto.split.syntax = TRUE # allow eta x eta interactions
)
summary(fit.lms)