knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) eval_semplots <- F
This tutorial introduces the mxmmod
package, for building Measurement Model of Derivatives (MMOD; Estabrook, 2015) with OpenMx.
A. Introduction to the Measurement Model of Derivatives (MMOD)
B. Data set
C. Example 1: One factor model
D. Example 2: Two factor model
E. Discussion
First, let's load the required libraries for this tutorial:
library(tidyverse) library(OpenMx) library(mxmmod)
The Measurement Model of Derivatives (MMOD; Estabrook, 2015) is a method for evaluating test item structures that includes the temporal dynamics of item responses. Unlike traditional confirmatory factor analysis which only evaluates factor structures cross-sectionally at a single time point, an MMOD operates longitudinally, taking into account how latent factors and their associated items change over time. The MMOD makes the assumption that items from the same construct will exhibit similar temporal dynamcs (as defined by their deratives). In doing so, the MMOD can uniquely identify factor structures that would otherwise be indistinguishable cross-sectionally. By reducing the ambiguity in factor structure, the MMOD is a powerful tool to validate and sharpen theoretical distinctions among constructs in longitudinal data.
This tutorial follows the example in Estabrook (2015) and makes use of data from the National Longitudinal Survey of Youth.
The NLSY 1997 sample (NLSY97) has a 5-item depression scale that was administered at three occasions.
The five items are all on a 4-point Likert scale.
Participants were asked how often they felt "like a nervous person", "calm and peaceful", "down or blue", "like a happy person", and "depressed" in the last month. These example data are included in the mxmmod
package:
data(nlsy97depression) summary(nlsy97depression)
Before building any models, we first plot a few example trajectories and mean trajectories for the five items assessed:
set.seed(1000) subset <- sample(unique(nlsy97depression$pid), 9) nlsy97depression %>% filter(pid %in% subset) %>% gather(measure, val, -pid, -occasion) %>% ggplot(aes(x=occasion, group=measure, color=measure, y=val)) + geom_line(position=position_jitter(w=0.1, h=0.1)) + facet_wrap(~pid)
nlsy97depression %>% gather(measure, val, -occasion, -pid) %>% na.omit() %>% ggplot(aes(x=occasion, color=measure, y=val)) + stat_summary(fun.y = mean, geom='line') + stat_summary(fun.y = mean, geom='point') + stat_summary(fun.data = mean_se, geom='errorbar', width=0.2)
We'll start by building a 1-factor MMOD, with all items loading onto a single latent factor.
structure <- list( F1 = c('nervous', 'down', 'depressed', 'calm', 'happy') ) mmod_model <- mxMmodModel(data=nlsy97depression, modelName='1 Factor MMOD', idvar='pid', timevar='occasion', structure=structure, fiml=F) mmod_fit <- mxRun(mmod_model) (mmod_summary <- summary(mmod_fit))
The path diagram of this MMOD can be rendered by semPlot::semPaths
# Note: This can take a while to draw... semPlot::semPaths(mmod_fit, 'est')
Next, let's build a two-factor MMOD with one latent factor for negative items (nervous, down, depressed), and the other for positive items (happy, calm):
structure2 <- list( F1 = c('nervous', 'down', 'depressed'), F2 = c('happy', 'calm') ) mmod_model2 <- mxMmodModel(data=nlsy97depression, modelName='2 Factor MMOD', idvar='pid', timevar='occasion', structure=structure2) mmod_fit2 <- mxRun(mmod_model2) (mmod_summary2 <- summary(mmod_fit2))
The path diagram of this MMOD can be rendered by semPlot::semPaths
# Note: This can take a while to draw... semPlot::semPaths(mmod_fit2, 'est')
Finally, let's create a summary table of the fits from the two models so we can compare:
fits <- list(mmod_summary, mmod_summary2) (compare_models <- tibble( name=map_chr(fits, 'modelName'), chisq=map_dbl(fits, 'Chi'), dof=map_dbl(fits, 'ChiDoF'), `-2ll`=map_dbl(fits, 'Minus2LogLikelihood'), aic=map_dbl(fits, 'AIC.Mx'), bic=map_dbl(fits, 'BIC.Mx'), rmsea=map_dbl(fits, 'RMSEA'), cfi=map_dbl(fits, 'CFI'), tli=map_dbl(fits, 'TLI') ))
The two-factor model is superior, across every fit metric.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.