Chapter 17 - Multivariate Latent Change Score Models
Nilam Ram, Kevin Grimm et al.
1 Overview
This tutorial walks through the fitting of a bivariate latent change score model in the structural equation modeling framework in R using using the lavaan
package.
The example follows Chapter 17 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) and reading comprehension ability (rec) from the second through eighth grade.
Reading in the data
#set filepath
<- "https://raw.githubusercontent.com/LRI-2/Data/main/GrowthModeling/nlsy_math_hyp_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', 'comp2', 'comp3', 'comp4', 'comp5', 'comp6', 'comp7', 'comp8', 'rec2', 'rec3', 'rec4', 'rec5', 'rec6', 'rec7', 'rec8', 'bpi2', 'bpi3', 'bpi4', 'bpi5', 'bpi6', 'bpi7', 'bpi8', 'asl2', 'asl3', 'asl4', 'asl5', 'asl6', 'asl7', 'asl8', 'ax2', 'ax3', 'ax4', 'ax5', 'ax6', 'ax7', 'ax8', 'hds2', 'hds3', 'hds4', 'hds5', 'hds6', 'hds7', 'hds8', 'hyp2', 'hyp3', 'hyp4', 'hyp5', 'hyp6', 'hyp7', 'hyp8', 'dpn2', 'dpn3', 'dpn4', 'dpn5', 'dpn6', 'dpn7', 'dpn8', 'wdn2', 'wdn3', 'wdn4', 'wdn5', 'wdn6', 'wdn7', 'wdn8', '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 'rec2', 'rec3', 'rec4', 'rec5', 'rec6', 'rec7', 'rec8')]
describe(nlsy_data)
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 |
rec2 | 9 | 333 | 34.68168 | 1.036303e+01 | 34.0 | 33.89888 | 10.3782 | 15 | 79 | 64 | 0.8084775 | 1.0583143 | 5.678904e-01 |
rec3 | 10 | 431 | 41.29002 | 1.146468e+01 | 40.0 | 40.80290 | 11.8608 | 19 | 81 | 62 | 0.4295972 | 0.0529361 | 5.522343e-01 |
rec4 | 11 | 376 | 47.55585 | 1.233346e+01 | 47.0 | 47.16556 | 11.8608 | 21 | 83 | 62 | 0.3227598 | -0.0742909 | 6.360496e-01 |
rec5 | 12 | 370 | 52.91351 | 1.303500e+01 | 52.0 | 52.86149 | 13.3434 | 21 | 84 | 63 | 0.0372454 | -0.4837760 | 6.776573e-01 |
rec6 | 13 | 389 | 55.99486 | 1.261831e+01 | 56.0 | 55.92971 | 13.3434 | 21 | 82 | 61 | -0.0293076 | -0.3703399 | 6.397735e-01 |
rec7 | 14 | 173 | 60.56069 | 1.360801e+01 | 62.0 | 61.15827 | 14.8260 | 23 | 84 | 61 | -0.3919243 | -0.5323470 | 1.034598e+00 |
rec8 | 15 | 142 | 64.37324 | 1.215246e+01 | 66.0 | 65.10526 | 13.3434 | 32 | 84 | 52 | -0.5032979 | -0.5582369 | 1.019812e+00 |
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',
'rec2', 'rec3', 'rec4', 'rec5', 'rec6', 'rec7', 'rec8'),
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 | rec | |
---|---|---|---|---|
201.2 | 201 | 2 | NA | NA |
201.3 | 201 | 3 | 38 | 35 |
201.4 | 201 | 4 | NA | NA |
201.5 | 201 | 5 | 55 | 52 |
201.6 | 201 | 6 | NA | NA |
201.7 | 201 | 7 | NA | NA |
201.8 | 201 | 8 | NA | NA |
303.2 | 303 | 2 | 26 | 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).