Chapter 16 - Latent Change Score Modeling
Nilam Ram, Kevin Grimm et al.
1 Overview
This tutorial walks through the fitting of univariate latent change score models in the structural equation modeling framework in R using using the lavaan
package.
The example follows Chapter 16 of Grimm, Ram, and Estabrook (2017). Please refer to the chapter for further interpretations and insights about the analyses.
1.0.1 Prelim - Loading libraries used in this script.
library(psych)
library(ggplot2)
library(corrplot) #plotting correlation matrices
library(lavaan) #for fitting structural equation models
library(semPlot) #for automatically making diagrams
1.0.2 Prelim - Reading in Repeated Measures Data
We use data from the NLSY-CYA (Center for Human Resource Research, 2009) that includes repeated measures of children’s math ability (math) from the second through eighth grade.
Reading in the data
#set filepath
<- "https://raw.githubusercontent.com/LRI-2/Data/main/GrowthModeling/nlsy_math_wide_R.dat"
filepath #read in the text data file using the url() function
<- read.table(file=url(filepath),na.strings = ".")
nlsy_data
#adding names for the columns of the data set
names(nlsy_data) <- c('id', 'female', 'lb_wght', 'anti_k1', 'math2', 'math3', 'math4', 'math5', 'math6', 'math7', 'math8', 'age2', 'age3', 'age4', 'age5', 'age6', 'age7', 'age8', 'men2', 'men3', 'men4', 'men5', 'men6', 'men7', 'men8', 'spring2', 'spring3', 'spring4', 'spring5', 'spring6', 'spring7', 'spring8', 'anti2', 'anti3', 'anti4', 'anti5', 'anti6', 'anti7', 'anti8')
#reduce data down to the id variable and the math and reading variables of interest
<- nlsy_data[ ,c('id', 'math2', 'math3', 'math4', 'math5', 'math6', 'math7', 'math8')]
nlsy_data
::describe(nlsy_data) psych
vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
id | 1 | 933 | 532334.89711 | 3.280208e+05 | 506602.0 | 520130.77108 | 391999.4400 | 201 | 1256601 | 1256400 | 0.2841659 | -0.9078872 | 1.073892e+04 |
math2 | 2 | 335 | 32.60896 | 1.028600e+01 | 32.0 | 32.27509 | 10.3782 | 12 | 60 | 48 | 0.2686681 | -0.4600130 | 5.619840e-01 |
math3 | 3 | 431 | 39.88399 | 1.029949e+01 | 41.0 | 39.88406 | 10.3782 | 13 | 67 | 54 | -0.0520929 | -0.3259168 | 4.961091e-01 |
math4 | 4 | 378 | 46.16931 | 1.016510e+01 | 46.0 | 46.22039 | 8.8956 | 18 | 70 | 52 | -0.0595783 | -0.0759665 | 5.228366e-01 |
math5 | 5 | 372 | 49.77419 | 9.471909e+00 | 48.0 | 49.76510 | 8.8956 | 23 | 71 | 48 | 0.0425474 | -0.3381126 | 4.910956e-01 |
math6 | 6 | 390 | 52.72308 | 9.915594e+00 | 50.5 | 52.38462 | 9.6369 | 24 | 78 | 54 | 0.2510417 | -0.3808615 | 5.020956e-01 |
math7 | 7 | 173 | 55.35260 | 1.062727e+01 | 53.0 | 55.08633 | 11.8608 | 31 | 81 | 50 | 0.2148479 | -0.9709622 | 8.079765e-01 |
math8 | 8 | 142 | 57.83099 | 1.153101e+01 | 56.0 | 57.42982 | 12.6021 | 26 | 81 | 55 | 0.1590545 | -0.5222967 | 9.676607e-01 |
1.0.3 Prelim - Plotting the Repeated Measures Data
#reshaping wide to wide
<- reshape(data=nlsy_data,
data_long varying = c('math2', 'math3', 'math4', 'math5', 'math6', 'math7', 'math8'),
timevar=c("grade"),
idvar=c("id"),
direction="long", sep="")
#sorting for easy viewing
#reorder by id and day
<- data_long[order(data_long$id,data_long$grade), ]
data_long
#looking at the long data
head(data_long, 8)
id | grade | math | |
---|---|---|---|
201.2 | 201 | 2 | NA |
201.3 | 201 | 3 | 38 |
201.4 | 201 | 4 | NA |
201.5 | 201 | 5 | 55 |
201.6 | 201 | 6 | NA |
201.7 | 201 | 7 | NA |
201.8 | 201 | 8 | NA |
303.2 | 303 | 2 | 26 |
#Plotting intraindividual change MATH
ggplot(data = data_long, aes(x = grade, y = math, group = id)) +
geom_point(color="blue") +
geom_line(color="blue") +
xlab("Grade") +
ylab("PIAT Mathematics") +
scale_x_continuous(limits=c(2,8), breaks=seq(2,8,by=1)) +
scale_y_continuous(limits=c(0,90), breaks=seq(0,90,by=10))
## Warning: Removed 4310 rows containing missing values (geom_point).
## Warning: Removed 2787 row(s) containing missing values (geom_path).