Skip to content

Commit

Permalink
Iron out documentation and clear CRAN check; increment version
Browse files Browse the repository at this point in the history
  • Loading branch information
khusmann committed Mar 16, 2020
1 parent 313c175 commit 2f51b18
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 29 deletions.
10 changes: 6 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: mxmmod
Type: Package
Title: Measurement Model of Derivatives (MMOD) in OpenMx
Version: 0.1.0
Version: 1.0.0
Authors@R: c(
person(
given = 'Kyle',
Expand All @@ -16,15 +16,17 @@ Authors@R: c(
)
)
Description: This package provides a convenient interface for building
Measurement Model of Derivatives (MMOD; Estabrook, 2015) in OpenMx
License: Apache 2.0
Measurement Model of Derivatives (MMOD; Estabrook, 2015) in OpenMx.
License: file LICENSE
Encoding: UTF-8
LazyData: true
Imports:
OpenMx
Suggests:
knitr,
rmarkdown,
testthat
testthat,
tidyverse
VignetteBuilder: knitr
RoxygenNote: 6.1.1
Depends: R (>= 2.10)
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
exportPattern("^[[:alpha:]]+")
# Generated by roxygen2: do not edit by hand

export(mxMmodModel)
19 changes: 19 additions & 0 deletions R/data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#' NLSY97 Longitudinal Depression Scale Data
#'
#' A 5-item depression scale used on the National Longitudinal
#' Survey of Youth, 1997 sample (NLSY97). Individuals were assessed
#' in 2000, 2002, and 2004. All items are assessed on a 4-point
#' likert scale.
#'
#' @format A data frame with 26952 rows and 7 variables:
#' \describe{
#' \item{pid}{Unique ID of participant}
#' \item{occasion}{Measurement occasion}
#' \item{nervous}{How often participant felt 'like a nervous person'}
#' \item{calm}{How often participant felt 'calm and peaceful'}
#' \item{down}{How often participant felt 'down or blue'}
#' \item{happy}{How often participant felt 'like a happy person'}
#' \item{depressed}{How often participant felt 'depressed'}
#' }
#' @source \url{https://www.bls.gov/nls/nlsy97.htm}
"nlsy97depression"
38 changes: 23 additions & 15 deletions R/mxMmodModel.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@
#' \code{list(F1 = c('m1', 'm2', 'm3'), F2 = c('m4', 'm5', 'm6'))}
#'
#' @examples
#' data("nlsy97depression")
#' data(nlsy97depression)
#' # Fit one factor MMOD
#' structure <- list(
#' F1 = c('nervous', 'down', 'depressed', 'calm', 'happy')
#' )
#' mmod_model <- mxMmodModel(data=nlsy97depression,
#' modelName='1 Factor MMOD',
#' idvar='pid', timevar='occasion', structure=structure)
#' mmod_fit <- mxRun(mmod_model)
#' mmod_fit <- OpenMx::mxRun(mmod_model)
#' summary(mmod_fit)
#' @export

mxMmodModel <- function(data, modelName, idvar, timevar, structure, fiml=F) {
derivName <- function(o, m) {paste0('d', m, '_', o)} # derivName(1, 'nervous') -> dnervous_1
Expand Down Expand Up @@ -107,53 +108,60 @@ mxMmodModel <- function(data, modelName, idvar, timevar, structure, fiml=F) {
manifests <- unique(unlist(derivStruct))

data <- data[c(idvar, timevar, unlist(structure))]
data <- reshape(as.data.frame(data), timevar=timevar, idvar=idvar, direction='wide', sep='_')[-1]
data <- stats::reshape(as.data.frame(data), timevar=timevar, idvar=idvar, direction='wide', sep='_')[-1]
stopifnot(setequal(manifests, names(data))) # Sanity check

# OpenMx manifest ordering bug: https://github.com/OpenMx/OpenMx/issues/247
data <- data[manifests]

if (fiml) {
mxd <- mxData(data, type="raw")
mxd <- OpenMx::mxData(data, type="raw")
} else {
if (any(is.na(data))) {
warning('Missing values detected; omitting them.')
}
df_subset <- na.omit(data)
df_cov <- cov(df_subset)
mxd <- mxData(df_cov, type="cov", numObs=nrow(df_subset))
df_subset <- stats::na.omit(data)
df_cov <- stats::cov(df_subset)
mxd <- OpenMx::mxData(df_cov, type="cov", numObs=nrow(df_subset))
}

# Make weight matrix with Deboeck’s functions
weight <- ContrastsGOLD(occasions_num, length(occasions_num) - 1)
weightList <- as.list(as.data.frame(t(weight)))

do.call('mxModel', c(list(
do.call(OpenMx::mxModel, c(list(
modelName, mxd, type="RAM",
manifestVars=manifests,
latentVars=c(factors, derivatives),
# factor loadings
mapply(function(fct, drv) {
mxPath(from=fct, to=drv, values=0.5, free=T)
OpenMx::mxPath(from=fct, to=drv, values=0.5, free=T)
}, names(factorStruct), factorStruct),
# factor variances
mxPath(from=factors, arrows=2, values=1, free=F),
OpenMx::mxPath(from=factors, arrows=2, values=1, free=F),
# factor correlations
mxPath(from=factors, arrows=2, connect="unique.bivariate", free=T),
OpenMx::mxPath(from=factors, arrows=2, connect="unique.bivariate", free=T),
# residual variances(only for latent derivatives !)
mxPath(from=derivatives, arrows=2, values=1)),
OpenMx::mxPath(from=derivatives, arrows=2, values=1)),
# transformation
mapply(function(dgrp, weight) {
mapply(function(drv, mnf) {
mxPath(from=drv, to=mnf, free=F, values=weight)
OpenMx::mxPath(from=drv, to=mnf, free=F, values=weight)
}, names(dgrp), dgrp)
}, derivStruct, weightList),
# saturate model
if (fiml) mxPath(from = 'one', to = manifests) else list()
if (fiml) OpenMx::mxPath(from = 'one', to = manifests) else list()
))
}

# Code from Deboeck (2010)
#' Generate GOLD contrasts
#'
#' Code from Deboeck (2010)
#'
#' @param T timeseries
#' @param max max derivatives
#'
#' @keywords internal
ContrastsGOLD <- function(T, max) {
Xi <- matrix(NA, length(T), length(T))
for(r in 0:(length(T)-1)) {
Expand Down
3 changes: 3 additions & 0 deletions data-raw/nlsy97depression.R
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Create nlsy97 depression data set
#
# Public domain data from nlsy97: https://www.bls.gov/nls/nlsy97.htm
#

var_list <- list(
pid = 'R0000100',
Expand Down
17 changes: 17 additions & 0 deletions man/ContrastsGOLD.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/mxMmodModel.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions man/nlsy97depression.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tests/testthat/test-refimpl.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
context('Reference implementation comparison')

mxmmod_ref <- function(df, do_fiml=F) {
require(OpenMx)
require(mxmmod)
structure <- list(
F1 = c('nervous', 'down', 'depressed', 'calm', 'happy')
Expand Down
9 changes: 2 additions & 7 deletions vignettes/mmod_tutorial.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ vignette: >
%\VignetteIndexEntry{Getting Started with mxmmod}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
%\VignetteDepends{tidyverse}
---

```{r setup, include = FALSE}
Expand Down Expand Up @@ -35,13 +36,7 @@ E. Discussion

### Prelim: Prepare environment

Before we begin, install the `mxmmod` package if you have not already:

```{r, eval=F}
devtools::install_github('khusmann/mxmmod')
```

Now let's load the required libraries for this tutorial:
First, let's load the required libraries for this tutorial:

```{r, message=F, warning=F}
library(tidyverse)
Expand Down

0 comments on commit 2f51b18

Please sign in to comment.