ctgimme estimates group-, subgroup-, and
individual-level continuous-time dynamic networks from intensive
longitudinal data using continuous-time subgrouping GIMME (C-TSGIMME).
It combines continuous-time state-space models with iterative searches
for temporal paths supported across the sample, shared within recovered
membership groups, or specific to individual subjects.
The method is described in:
Park, J. J., Fisher, Z. F., Hunter, M. D., Shenk, C., Russell, M., Molenaar, P. C. M., and Chow, S.-M. (2025). Unsupervised model construction in continuous-time. Structural Equation Modeling: A Multidisciplinary Journal, 32(3), 377–399. https://doi.org/10.1080/10705511.2024.2429544
Install the current release directly from GitHub:
if (!requireNamespace("remotes", quietly = TRUE)) {
install.packages("remotes")
}
remotes::install_github("JPark93/ctgimme", dependencies = TRUE)Install the 0.0.12 source archive while also resolving dependencies:
remotes::install_local(
"path/to/ctgimme_0.0.12.tar.gz",
dependencies = TRUE
)If the dependencies are already installed, base R can install the archive:
install.packages(
"path/to/ctgimme_0.0.12.tar.gz",
repos = NULL,
type = "source"
)The imported dependencies, including OpenMx, are listed in
DESCRIPTION. Package expm is required when
subgroup.model = TRUE; igraph and
nloptr support the optional legacy subgrouping workflow.
Building or checking from a source checkout on Windows may require the
Rtools version appropriate for the installed version of R.
The primary function, ctgimme(), expects a data frame in
long format with one row per observation. The id and
time arguments name the subject and observation-time
columns, and varnames names the modeled variables. These
columns may appear in any position. Identifier and time values must be
nonmissing; observation times and nonmissing modeled values must be
finite and numeric. Rows are not sorted internally, so they must already
be ordered by time within subject. Missing modeled values are passed to
OpenMx’s raw-data likelihood.
The order of varnames determines the order of variables
in the fitted drift and noise matrices. Subject identifiers are also
used in intermediate filenames and therefore must be valid portable
filename components. The identifier values must also remain unique when
compared without case, because common Windows and macOS filesystems are
case-insensitive. The selected time column is copied internally to a
reserved column named Time; do not use Time as
the name of a modeled process variable.
library(ctgimme)
result <- ctgimme(
varnames = c("x1", "x2", "x3"),
dataframe = my_long_data,
id = "subject_id",
time = "observation_time",
subgroup.method = "pam",
sub.sig.thrsh = 0.55,
max.subgroups = 4,
cores = 1,
directory = "ctgimme-output",
verbose = TRUE
)Set verbose = FALSE to suppress package progress
messages and OpenMx optimizer reporting. Warnings and errors remain
available through standard R condition handling, and the returned object
and written artifacts are the same under either setting.
sig.thrsh = 0.55 requires a candidate group path to have
significant modification-index support from at least 55% of subjects
with usable results. Galpha = 0.05 supplies the base
group-level significance threshold. The analogous subgroup defaults are
sub.sig.thrsh = 1 and S.Galpha = 0.05, and the
individual-level base threshold is Ialpha = 0.01. With the
default ben.hoch = TRUE, these alpha values seed an
adapted, progressively stricter threshold sequence for path additions;
FALSE uses the corresponding alpha at every step. A group-
or membership-group shared search adds no path when usable
modification-index results are available for no more than half of the
subjects requested for that search.
The default sub.sig.thrsh = 1 bypasses data-driven
subgroup detection and assigns all subjects to membership group 1. It
does not skip the subsequent within-group shared-path search or
individual-model fits. Set it below one to activate
subgroup.method. The default method, "pam",
screens recurrent signed evidence for eligible non-group paths, computes
mean Manhattan distances, and selects the candidate with the largest
average silhouette width. Active PAM subgrouping requires
max.subgroups to be an integer of at least two; the actual
upper candidate count is also limited to one less than the number of
subjects with usable features. Its recurrence screen uses fixed
0.05 subject-evidence and BH-adjusted recurrence
thresholds, independently of ben.hoch.
The alternative subgroup.method = "legacy" uses a
weighted similarity graph and Walktrap community detection and requires
igraph. With conduct = TRUE, the default, its
graph cutoff is optimized with nloptr; set
conduct = FALSE to use the unoptimized similarity weights
shifted to start at zero.
Set scale.data = TRUE to standardize each modeled
variable separately within subject before all estimation stages. The
default is FALSE; constant within-subject columns are
centered to zero when scaling is requested.
By default, measurement-error and process-noise variances are fixed
at the values supplied through ME.var and
PE.var: ME.var defaults to 1e-8,
whereas PE.var = NULL produces an identity matrix. Set
ME.free = TRUE or PE.free = TRUE to estimate
every diagonal variance, using the corresponding variance argument as
its starting value. Logical vectors allow selective estimation in the
order given by varnames:
result <- ctgimme(
varnames = c("x1", "x2", "x3"),
dataframe = my_long_data,
id = "subject_id",
time = "observation_time",
directory = "ctgimme-output",
ME.var = 0.05,
ME.free = FALSE,
PE.var = 1,
PE.free = c(TRUE, TRUE, FALSE)
)Only diagonal measurement-error and process-noise variances are
supported; off-diagonal covariances remain fixed to zero. Estimating
both sets of variances can require substantially more within-person
information than estimating process noise while fixing measurement
error. Estimated process-noise and measurement-error variances are
stored in the Q and R matrices, respectively,
of each saved OpenMx model.
The default subgroup.model = FALSE skips only the
additional joint, parameterized model for each membership group;
subgroup-level structural searches and individual fits still run. Set it
to TRUE to fit one shared-parameter model per subgroup and
write its coefficient plot, discrete-time transition plots, and
fitted-model RDS file. This workflow requires expm.
result <- ctgimme(
...,
subgroup.model = TRUE,
time.intervals = c(0.25, 1, 2)
)The subgroup model is estimated from the summed likelihoods of its
members. Each member has an independently initialized continuous-time
state-space filter, so no state is propagated across subject boundaries
and no trajectories are concatenated. The saved result is one fitted
OpenMx model with one top-level A, Q, and
R; its subject children are likelihood blocks, not
separately estimated parameter models. This creates one fitted joint
model for each subgroup, not one fitted parameter model per member. Each
subject’s observation times are rebased to its first observation,
preserving all within-person elapsed intervals while removing arbitrary
calendar offsets.
time.intervals remains the only subgroup-model time
control. For every requested nonnegative delta t, ctgimme computes
exp(A * delta_t) and writes the discrete-time transition
plot. For subgroup g, the files are written to
Models/Subgroup <g>/ with these names:
Subgroup <g> Params.png;Subgroup <g> Delta_t = <delta>.png for
every requested delta t; andSubgroup_<g>Model.RDS, containing the single
fitted joint model.All internal mxTryHard() calls pass through one package
wrapper. With verbose = TRUE, package stage messages and
ordinary optimizer reporting from fits in the main R process are shown;
PSOCK workers do not forward raw console output. With
verbose = FALSE, package messages and main-process OpenMx
output are suppressed so a quiet run remains quiet. Subgroup parameter
plots also supply edge labels as a square matrix, as required by
qgraph for the fitted drift matrix. Parameter and
transition plots use expanded margins so boundary nodes, loops, titles,
and labels are not clipped in the saved PNG files.
For a first run on a new computer, use cores = 1 and a
new, empty output directory. After that run succeeds,
cores = 2 can reduce elapsed time, at the cost of the
memory used by one additional R/OpenMx worker. Requests above two are
reduced to the package-wide two-worker maximum.
When enabled subgroup detection succeeds, the function returns the
selected PAM or Walktrap clustering object. Both forms carry the
complete, ID-aligned vector in
attr(result, "ctgimme.membership"); PAM results
additionally expose the same vector as result$membership.
If PAM has fewer than three usable subject model/MI pairs or no
recurrent eligible features, or legacy detection has fewer than two
usable pairs, detection falls back to one membership group and the
function invisibly returns a result list containing the complete
membership, group structure, output directory, and subgroup diagnostics.
A successfully computed legacy solution may itself contain one community
and still returns its communities object.
When sub.sig.thrsh = 1, the same result-list form
includes the group structure, complete membership vector, output
directory, subgroup-detection record, and completion message. Thus every
successful return directly exposes the complete membership. Every
successfully completed run also saves it to
subgroup_membership.csv and
subgroup_detection.rds. Subjects without usable model/MI
artifacts are assigned to group 1 in these complete outputs.
The output directory includes:
GStruc.RDS, containing the group-level structure;SGStruc*.RDS, containing the shared structure for each
membership group, including the single group used when detection is
disabled or falls back;subgroup_membership.csv, mapping every subject
identifier to a subgroup;Subgroups Plot.png, showing a subject-distance map when
diagnostic distances are available and a complete membership roster
otherwise;subgroup_detection.rds, containing subgroup
diagnostics; andModels/Individuals.Successful PAM detection also writes
pam_silhouette_selection.png; successful legacy detection
writes walktrap_community_plot.png. With
subgroup.model = TRUE, each successfully fitted
membership-group model is written as
Subgroup_<g>Model.RDS, together with
Subgroup <g> Params.png and one
Subgroup <g> Delta_t = <delta>.png for every
requested delta t. By default, keep.intermediate = FALSE
removes temporary per-subject Model_<id>.RDS and
MI_<id>.RDS search files after successful completion;
final individual and pooled membership-group models are retained.
For PAM subgrouping, the plot uses classical multidimensional scaling of the same mean Manhattan distances used for clustering. Mapped subjects that are closer in the plot have more similar recurrent-evidence profiles. Colors and enclosing hulls show subgroup membership, while nearest-neighbor edges aid visual interpretation. The two-dimensional display is an approximation; its reported goodness-of-fit summarizes how well it represents the full distance matrix. Subjects lacking a diagnostic distance are named on the plot but are not placed on the map.
The cores argument defaults to one. Explicit requests
are bounded by both the number of subjects and a package-wide maximum of
two workers, in accordance with CRAN policy. OpenMx is set to one thread
in each R process during the run, and the calling process’s previous
OpenMx thread setting is restored on exit.
For cores > 1, ctgimme creates one PSOCK
worker pool and reuses it for the group, subgroup, and individual
fitting batches. Workers load OpenMx and qgraph once, wait idle while
the main R process pools modification indices and selects the next path
or subgroup, and then receive the next fitting batch. The pool is
stopped when the analysis finishes or exits with an error.
ctgimme_demo() provides a deterministic, lightweight
demonstration of the feature-selection and subgrouping logic without
fitting OpenMx models:
demo <- ctgimme_demo()
demo$membership
demo$candidatesThe demonstration avoids OpenMx fitting and deterministically recovers its known two-subgroup partition.
Use the package citation and its methodological reference with:
citation("ctgimme")See the contributing guide for the test and pull-request workflow. Release notes are maintained in NEWS.md.
ctgimme is authored by Jonathan J. Park
(imJPark@UCDavis.edu)
and Nathan Xin Mills
(nxmills@berkeley.edu).
The package is distributed under the Apache License 2.0.