Along the same purpose with tutorials of previous chapters. This tutorial walks through the fitting of latent change score model (dual change model) in the structural equation framework. In this tutorial, we will be using a sample data set that includes repeated measures of individuals’ mathematics achievement through elementary and middle school (dataset named as nlsy_math_wide_R.dat in the original dataset accompanying the book, and here we converted to a csv file, see link on the left).
The data, code and example provided in this tutorial are adapted from Chapter 16 of Grimm, Ram, and Estabrook (2016), with a few additions in code and commentary. Please refer to the chapter for further interpretations and insights about the analyses.
This tutorial provides line-by-line code to
library(nlme)
require(lavaan)
require(dplyr)
require(tidyr)
For this tutorial, we will access the relevant data through the QuantDev website by first setting the file path to the data file, and then using the read.csv()
to load these data into R.
# Set filepath
filepath_wide <- "https://quantdev.ssri.psu.edu/sites/qdev/files/nlsy_math_wide.csv"
# Read in the .csv file using the url() function
nlsy_math_wide <- read.csv(file = url(filepath_wide), header=TRUE)
summary(nlsy_math_wide)
## id female lb_wght anti_k1
## Min. : 201 Min. :0.000 Min. :0.00000 Min. :0.000
## 1st Qu.: 261503 1st Qu.:0.000 1st Qu.:0.00000 1st Qu.:0.000
## Median : 506602 Median :0.000 Median :0.00000 Median :1.000
## Mean : 532335 Mean :0.492 Mean :0.08039 Mean :1.454
## 3rd Qu.: 794503 3rd Qu.:1.000 3rd Qu.:0.00000 3rd Qu.:2.000
## Max. :1256601 Max. :1.000 Max. :1.00000 Max. :8.000
##
## math2 math3 math4 math5
## Min. :12.00 Min. :13.00 Min. :18.00 Min. :23.00
## 1st Qu.:25.00 1st Qu.:32.00 1st Qu.:40.00 1st Qu.:44.00
## Median :32.00 Median :41.00 Median :46.00 Median :48.00
## Mean :32.61 Mean :39.88 Mean :46.17 Mean :49.77
## 3rd Qu.:40.00 3rd Qu.:47.00 3rd Qu.:52.00 3rd Qu.:57.00
## Max. :60.00 Max. :67.00 Max. :70.00 Max. :71.00
## NA's :598 NA's :502 NA's :555 NA's :561
## math6 math7 math8 age2
## Min. :24.00 Min. :31.00 Min. :26.00 Min. : 82.00
## 1st Qu.:46.00 1st Qu.:47.00 1st Qu.:49.00 1st Qu.: 93.00
## Median :50.50 Median :53.00 Median :56.00 Median : 97.00
## Mean :52.72 Mean :55.35 Mean :57.83 Mean : 97.22
## 3rd Qu.:61.00 3rd Qu.:63.00 3rd Qu.:66.00 3rd Qu.:101.00
## Max. :78.00 Max. :81.00 Max. :81.00 Max. :121.00
## NA's :543 NA's :760 NA's :791 NA's :598
## age3 age4 age5 age6
## Min. : 92.0 Min. :105.0 Min. :115 Min. :127.0
## 1st Qu.:104.0 1st Qu.:116.0 1st Qu.:129 1st Qu.:140.0
## Median :108.0 Median :120.5 Median :133 Median :144.0
## Mean :108.6 Mean :120.8 Mean :133 Mean :144.8
## 3rd Qu.:113.0 3rd Qu.:125.0 3rd Qu.:137 3rd Qu.:150.0
## Max. :133.0 Max. :151.0 Max. :155 Max. :170.0
## NA's :502 NA's :555 NA's :561 NA's :543
## age7 age8 men2 men3
## Min. :140.0 Min. :155.0 Min. :0 Min. :0.0000
## 1st Qu.:154.0 1st Qu.:163.2 1st Qu.:0 1st Qu.:0.0000
## Median :157.0 Median :167.0 Median :0 Median :0.0000
## Mean :157.4 Mean :166.6 Mean :0 Mean :0.0043
## 3rd Qu.:161.0 3rd Qu.:170.0 3rd Qu.:0 3rd Qu.:0.0000
## Max. :173.0 Max. :175.0 Max. :0 Max. :1.0000
## NA's :760 NA's :791 NA's :781 NA's :699
## men4 men5 men6 men7
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000
## Median :0.0000 Median :0.0000 Median :0.0000 Median :1.0000
## Mean :0.0417 Mean :0.1129 Mean :0.3081 Mean :0.7308
## 3rd Qu.:0.0000 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.0000
## NA's :765 NA's :747 NA's :748 NA's :855
## men8 spring2 spring3 spring4
## Min. :0.0000 Min. :0.000 Min. :0.0000 Min. :0.0000
## 1st Qu.:1.0000 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.:0.0000
## Median :1.0000 Median :1.000 Median :1.0000 Median :1.0000
## Mean :0.9296 Mean :0.609 Mean :0.5452 Mean :0.6455
## 3rd Qu.:1.0000 3rd Qu.:1.000 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.000 Max. :1.0000 Max. :1.0000
## NA's :862 NA's :598 NA's :502 NA's :555
## spring5 spring6 spring7 spring8
## Min. :0.0000 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:1.0000 1st Qu.:0.0000
## Median :1.0000 Median :1.0000 Median :1.0000 Median :1.0000
## Mean :0.6613 Mean :0.7077 Mean :0.7861 Mean :0.7183
## 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000 3rd Qu.:1.0000
## Max. :1.0000 Max. :1.0000 Max. :1.0000 Max. :1.0000
## NA's :561 NA's :543 NA's :760 NA's :791
## anti2 anti3 anti4 anti5
## Min. :0.000 Min. :0.000 Min. :0.000 Min. :0.000
## 1st Qu.:0.000 1st Qu.:0.000 1st Qu.:0.000 1st Qu.:0.000
## Median :1.000 Median :1.000 Median :1.000 Median :1.000
## Mean :1.482 Mean :1.544 Mean :1.535 Mean :1.572
## 3rd Qu.:2.000 3rd Qu.:2.000 3rd Qu.:2.000 3rd Qu.:3.000
## Max. :8.000 Max. :8.000 Max. :7.000 Max. :8.000
## NA's :603 NA's :512 NA's :563 NA's :571
## anti6 anti7 anti8
## Min. :0.000 Min. :0.000 Min. :0.000
## 1st Qu.:0.000 1st Qu.:1.000 1st Qu.:0.000
## Median :1.000 Median :1.000 Median :1.000
## Mean :1.693 Mean :1.681 Mean :1.586
## 3rd Qu.:3.000 3rd Qu.:3.000 3rd Qu.:2.250
## Max. :8.000 Max. :7.000 Max. :8.000
## NA's :555 NA's :764 NA's :793
model.syntax <- "
# latent variables are indicated by the observed variables (also considered factor loadings)
ly1 =~ 1* math2 # ly1 is indicated by math2, factor loading = 1
ly2 =~ 1* math3
ly3 =~ 1* math4
ly4 =~ 1* math5
ly5 =~ 1* math6
ly6 =~ 1* math7
ly7 =~ 1* math8
dy2 =~ 1 * ly2 # dy2 is indicated by ly2, factor loading = 1
dy3 =~ 1 * ly3
dy4 =~ 1 * ly4
dy5 =~ 1 * ly5
dy6 =~ 1 * ly6
dy7 =~ 1 * ly7
# the constant change, g2, is indicated by dy2~dy7
g2 =~ 1*dy2 + 1*dy3 + 1*dy4 + 1*dy5 + 1*dy6 + 1*dy7
# factor means
ly1 ~ 1
g2 ~ 1
# regressions
ly2 ~ 1 * ly1 + 1 * dy2 # ly2 is regressed on ly1 and dy2, regression coefficient is fixed at 1
ly3 ~ 1 * ly2 + 1 * dy3
ly4 ~ 1 * ly3 + 1 * dy4
ly5 ~ 1 * ly4 + 1 * dy5
ly6 ~ 1 * ly5 + 1 * dy6
ly7 ~ 1 * ly6 + 1 * dy7
# autoproportions, the changes of dy2 to dy7 is also proportional to ly1 to ly6, respectively
dy2 ~ pi * ly1 # dy2 is regressed on ly1, the regression coefficient is estimated as pi
dy3 ~ pi * ly2
dy4 ~ pi * ly3
dy5 ~ pi * ly4
dy6 ~ pi * ly5
dy7 ~ pi * ly6
# covariances among factors
ly1 ~~ ly1
g2 ~~ g2
ly1 ~~ g2
ly2 ~~ 0*ly2
ly3 ~~ 0*ly3
ly4 ~~ 0*ly4
ly5 ~~ 0*ly5
ly6 ~~ 0*ly6
ly7 ~~ 0*ly7
dy2 ~~ 0*dy2
dy2 ~~ 0*dy3
dy2 ~~ 0*dy4
dy2 ~~ 0*dy5
dy2 ~~ 0*dy6
dy2 ~~ 0*dy7
dy3 ~~ 0*dy3
dy3 ~~ 0*dy4
dy3 ~~ 0*dy5
dy3 ~~ 0*dy6
dy3 ~~ 0*dy7
dy4 ~~ 0*dy4
dy4 ~~ 0*dy5
dy4 ~~ 0*dy6
dy4 ~~ 0*dy7
dy5 ~~ 0*dy5
dy5 ~~ 0*dy6
dy5 ~~ 0*dy7
dy6 ~~ 0*dy6
dy6 ~~ 0*dy7
dy7 ~~ 0*dy7
# manifest variances (made equivalent by naming sigma2u)
math2 ~~ sigma2u*math2
math3 ~~ sigma2u*math3
math4 ~~ sigma2u*math4
math5 ~~ sigma2u*math5
math6 ~~ sigma2u*math6
math7 ~~ sigma2u*math7
math8 ~~ sigma2u*math8
# manifest means (fixed at zero)
math2 ~ 0
math3 ~ 0
math4 ~ 0
math5 ~ 0
math6 ~ 0
math7 ~ 0
math8 ~ 0
"
fit.lcs <- sem(model.syntax,
data=nlsy_math_wide,
missing = "fiml",
estimator = "ml"
)
summary(fit.lcs)
## lavaan (0.5-23.1097) converged normally after 32 iterations
##
## Used Total
## Number of observations 932 933
##
## Number of missing patterns 60
##
## Estimator ML
## Minimum Function Test Statistic 58.308
## Degrees of freedom 28
## P-value (Chi-square) 0.001
##
## Parameter Estimates:
##
## Information Observed
## Standard Errors Standard
##
## Latent Variables:
## Estimate Std.Err z-value P(>|z|)
## ly1 =~
## math2 1.000
## ly2 =~
## math3 1.000
## ly3 =~
## math4 1.000
## ly4 =~
## math5 1.000
## ly5 =~
## math6 1.000
## ly6 =~
## math7 1.000
## ly7 =~
## math8 1.000
## dy2 =~
## ly2 0.000
## dy3 =~
## ly3 0.000
## dy4 =~
## ly4 0.000
## dy5 =~
## ly5 0.000
## dy6 =~
## ly6 0.000
## dy7 =~
## ly7 0.000
## g2 =~
## dy2 1.000
## dy3 1.000
## dy4 1.000
## dy5 1.000
## dy6 1.000
## dy7 1.000
##
## Regressions:
## Estimate Std.Err z-value P(>|z|)
## ly2 ~
## ly1 1.000
## dy2 1.000
## ly3 ~
## ly2 1.000
## dy3 1.000
## ly4 ~
## ly3 1.000
## dy4 1.000
## ly5 ~
## ly4 1.000
## dy5 1.000
## ly6 ~
## ly5 1.000
## dy6 1.000
## ly7 ~
## ly6 1.000
## dy7 1.000
## dy2 ~
## ly1 (pi) -0.241 0.018 -13.387 0.000
## dy3 ~
## ly2 (pi) -0.241 0.018 -13.387 0.000
## dy4 ~
## ly3 (pi) -0.241 0.018 -13.387 0.000
## dy5 ~
## ly4 (pi) -0.241 0.018 -13.387 0.000
## dy6 ~
## ly5 (pi) -0.241 0.018 -13.387 0.000
## dy7 ~
## ly6 (pi) -0.241 0.018 -13.387 0.000
##
## Covariances:
## Estimate Std.Err z-value P(>|z|)
## ly1 ~~
## g2 13.746 1.699 8.092 0.000
## .dy2 ~~
## .dy3 0.000
## .dy4 0.000
## .dy5 0.000
## .dy6 0.000
## .dy7 0.000
## .dy3 ~~
## .dy4 0.000
## .dy5 0.000
## .dy6 0.000
## .dy7 0.000
## .dy4 ~~
## .dy5 0.000
## .dy6 0.000
## .dy7 0.000
## .dy5 ~~
## .dy6 0.000
## .dy7 0.000
## .dy6 ~~
## .dy7 0.000
##
## Intercepts:
## Estimate Std.Err z-value P(>|z|)
## ly1 32.533 0.434 74.955 0.000
## g2 15.222 0.815 18.687 0.000
## .math2 0.000
## .math3 0.000
## .math4 0.000
## .math5 0.000
## .math6 0.000
## .math7 0.000
## .math8 0.000
## .ly2 0.000
## .ly3 0.000
## .ly4 0.000
## .ly5 0.000
## .ly6 0.000
## .ly7 0.000
## .dy2 0.000
## .dy3 0.000
## .dy4 0.000
## .dy5 0.000
## .dy6 0.000
## .dy7 0.000
##
## Variances:
## Estimate Std.Err z-value P(>|z|)
## ly1 71.900 6.548 10.980 0.000
## g2 5.602 0.837 6.695 0.000
## .ly2 0.000
## .ly3 0.000
## .ly4 0.000
## .ly5 0.000
## .ly6 0.000
## .ly7 0.000
## .dy2 0.000
## .dy3 0.000
## .dy4 0.000
## .dy5 0.000
## .dy6 0.000
## .dy7 0.000
## .math2 (sgm2) 30.818 1.700 18.126 0.000
## .math3 (sgm2) 30.818 1.700 18.126 0.000
## .math4 (sgm2) 30.818 1.700 18.126 0.000
## .math5 (sgm2) 30.818 1.700 18.126 0.000
## .math6 (sgm2) 30.818 1.700 18.126 0.000
## .math7 (sgm2) 30.818 1.700 18.126 0.000
## .math8 (sgm2) 30.818 1.700 18.126 0.000
The result is the same with the OpenMX result on page 417 (output 16.2).
Ghisletta, P., & McArdle, J. J. (2012). Teacher’s Corner: Latent Curve Models and Latent Change Score Models Estimated in R. Structural Equation Modeling, 19(4): 651-682. doi:10.1080/10705511.2012.713275.
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4259494/pdf/nihms412332.pdf