The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Latent growth models with missing data

Scope

A latent growth curve model describes change across repeated measurements with latent intercept and slope factors. From semTests’ point of view, it is a continuous SEM. The usual robust p-values therefore work, including with full-information maximum likelihood (FIML) when a few repeated measurements have gone missing.

We will fit a linear trajectory, check its overall fit, and then ask whether a more flexible shape fits noticeably better.

library("semTests")
library("lavaan")

growth_data <- Demo.growth

A reproducible missing-data mechanism

Demo.growth is complete. To exercise FIML, missingness in the later waves t3 and t4 depends on the first wave t1. This gives the example a reproducible MAR-like mechanism and says nothing about a real missingness process.

set.seed(20260718)
driver <- as.numeric(scale(growth_data$t1))
growth_data$t3[runif(nrow(growth_data)) < plogis(qlogis(.20) + .8 * driver)] <- NA
growth_data$t4[runif(nrow(growth_data)) < plogis(qlogis(.20) + .8 * driver)] <- NA
colMeans(is.na(growth_data[paste0("t", 1:4)]))
#>    t1    t2    t3    t4 
#> 0.000 0.000 0.195 0.190

Linear growth under FIML

The linear model fixes the slope loadings to 0, 1, 2, 3:

linear <- growth(
  "i =~ 1*t1 + 1*t2 + 1*t3 + 1*t4
   s =~ 0*t1 + 1*t2 + 2*t3 + 3*t4",
  growth_data,
  missing = "fiml", estimator = "MLR"
)

pvalues(linear, c("SB", "SS", "ALL", "PEBA4"))
#>      sb_ml      ss_ml     all_ml   peba4_ml 
#> 0.09706262 0.09900832 0.09857646 0.09741806 
#> estimator: ML (MLR) (FIML) | data: continuous | information: observed | df: 5 | FIML convention: observed

FIML uses the standard likelihood-ratio statistic and the observed-information convention by default. The footer records both choices, so they do not vanish when the result is copied into another script.

Is the growth linear?

A latent-basis model frees the last two slope loadings and lets the data choose the shape of change. Linear growth fixes those loadings to 2 and 3, which makes it a special case of the latent-basis model. The linear model is the more constrained fit, so it goes first:

basis <- growth(
  "i =~ 1*t1 + 1*t2 + 1*t3 + 1*t4
   s =~ 0*t1 + 1*t2 + t3 + t4",
  growth_data,
  missing = "fiml", estimator = "MLR"
)

pvalues_nested(linear, basis, tests = c("SB", "SS", "ALL", "PEBA2"))
#>     sb_ml     ss_ml    all_ml  peba2_ml 
#> 0.5701799 0.5691468 0.5692181 0.5699399 
#> estimator: ML (MLR) (FIML) | data: continuous | information: observed | df: 2 | FIML convention: observed | nested (method 2000, A.method delta)

A small p-value would be evidence that the linear shape is too rigid. A large one means this comparison found no clear reason to let the trajectory bend. The two freed loadings give a two-degree-of-freedom test, so we use PEBA2. The number of blocks cannot exceed the test degrees of freedom.

The missing-data details are collected in vignette("fiml-missing-data", package = "semTests").

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.