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.

Temporal dynamics: choosing a model for ILD

tidyILD authors

2026-04-17

This article is a decision guide for temporal structure: lags in the mean, residual autocorrelation, time-varying effects, and latent dynamics. It does not replace statistical theory or domain expertise; it maps scientific questions to tidyILD entry points you already have.

Three axes before you fit anything

  1. Estimand — Associational lag effect? Stability of the outcome (lagged outcome in the mean)? Causal effect under a clear identification strategy (see MSM vignettes)? Latent smooth trajectory?
  2. Spacing — Occasions are regular-ish or irregular-ish? See ild_spacing_class(), ild_spacing(), and vignette("ild-decomposition-and-spacing", package = "tidyILD").
  3. Where dynamics live — In the fixed-effects mean (e.g. y ~ x_lag1), in residual correlation (AR1/CAR1 on within-person residuals), in a smooth over calendar/study time (ild_tvem()), or in a latent state (ild_kfas(), ild_ctsem()).

Decision flow (conceptual)

The following diagram is a navigation aid (rendered on sites that support Mermaid; otherwise read the labels as a checklist). Source in Mermaid syntax:

flowchart TD
  q1[Estimand clear?]
  spacing[Check ild_spacing_class]
  meanLag[Lags in mean: ild_lag ild_panel_lag_prepare ild_crosslag]
  residAR[Residual AR: ild_lme ar1=TRUE]
  tvem[Effect varies over time: ild_tvem]
  ct[Continuous-time latent: ild_ctsem]
  kfas[Discrete-time latent level: ild_kfas]
  q1 --> spacing
  spacing --> meanLag
  spacing --> residAR
  meanLag --> residAR
  spacing --> tvem
  spacing --> ct
  spacing --> kfas

Feature map

Question tidyILD tools Backend / notes Not a substitute for
Lagged predictor → outcome ild_lag(), ild_crosslag(), ild_panel_lag_prepare() ild_lme / ild_brms Full panel VAR / DSEM (multivariate lag system)
Lagged outcome (stability) Same lag helpers; model y ~ y_lag1 + ... carefully Mixed model Dynamic structural equation modeling software if that is the estimand
Residual serial correlation ild_lme(..., ar1 = TRUE) nlme AR1 or CAR1 Does not add lagged mean structure by itself
Effect changes over study time ild_tvem(), ild_tvem_plot() mgcv GAM Random slopes over time per person (consider ild_brms recipes)
Discrete-time latent level ild_kfas() KFAS Pooled multilevel latent model across many IDs
Continuous-time latent dynamics ild_ctsem() ctsem / Stan Quick lag regression on irregular data without CT assumptions
Compare a few fitted models ild_compare_fits() AIC/BIC where defined Likelihood-ratio tests unless models are nested and comparable
Multivariate lags / feedback (joint system) Same lag helpers; ild_crosslag() is one equation at a time Export preprocessed data; see vignette("ild-specialist-backends", package = "tidyILD") dynamite, lavaan DSEM, multivariate brms / ctsem
High-dimensional time-varying predictors (p >> n) Unpenalized ild_lme / lme4 is not designed for this Same vignette: hand off to penalized longitudinal tools PGEE and related methods

Minimal examples

library(tidyILD)
set.seed(1)
d <- ild_simulate(n_id = 12, n_obs_per = 10, seed = 1)
x <- ild_prepare(d, id = "id", time = "time")
out <- ild_crosslag(x, y, y, lag = 1L, ar1 = FALSE, warn_no_ar1 = FALSE)
#> boundary (singular) fit: see help('isSingular')
out$lag_term[, c("term", "estimate", "std_error")]
#> # A tibble: 1 × 3
#>   term   estimate std_error
#>   <chr>     <dbl>     <dbl>
#> 1 y_lag1    0.778    0.0607
x2 <- ild_center(x, y)
fit_ar <- tryCatch(
  ild_lme(y ~ y_bp + y_wp, data = x2, ar1 = TRUE, warn_no_ar1 = FALSE, warn_uncentered = FALSE),
  error = function(e) NULL
)
if (!is.null(fit_ar)) {
  print(fit_ar)
} else {
  "nlme fit skipped on this platform"
}
#> [1] "nlme fit skipped on this platform"
x3 <- ild_simulate(n_id = 10, n_obs_per = 15, seed = 2)
x3$x <- rnorm(nrow(x3))
x3 <- ild_prepare(x3, id = "id", time = "time")
tv <- ild_tvem(x3, "y", "x", k = 5, re_id = TRUE)
summary(tv)
#> 
#> Family: gaussian 
#> Link function: identity 
#> 
#> Formula:
#> y ~ s(.ild_time_num, k = 5) + s(.ild_time_num, by = x, k = 5) + 
#>     s(.ild_id, bs = "re")
#> 
#> Parametric coefficients:
#>             Estimate Std. Error t value Pr(>|t|)   
#> (Intercept)   0.9312     0.3205   2.905  0.00429 **
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Approximate significance of smooth terms:
#>                      edf Ref.df     F p-value    
#> s(.ild_time_num)   2.514  3.025 23.05  <2e-16 ***
#> s(.ild_time_num):x 2.000  2.000  0.94   0.393    
#> s(.ild_id)         8.820  9.000 49.59  <2e-16 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> R-sq.(adj) =  0.779   Deviance explained = 79.9%
#> GCV = 0.33544  Scale est. = 0.30339   n = 150

Further reading

#> R version 4.5.3 (2026-03-11)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS Sequoia 15.6
#> 
#> Matrix products: default
#> BLAS:   /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRblas.0.dylib 
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.1
#> 
#> locale:
#> [1] C/en_US/en_US/C/en_US/en_US
#> 
#> time zone: America/New_York
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] ggplot2_4.0.0 dplyr_1.1.4   tidyILD_0.4.0
#> 
#> loaded via a namespace (and not attached):
#>  [1] sandwich_3.1-1     sass_0.4.10        utf8_1.2.6         generics_0.1.4    
#>  [5] anytime_0.3.12     lattice_0.22-9     lme4_1.1-37        digest_0.6.37     
#>  [9] magrittr_2.0.4     evaluate_1.0.5     grid_4.5.3         timechange_0.3.0  
#> [13] RColorBrewer_1.1-3 fastmap_1.2.0      jsonlite_2.0.0     Matrix_1.7-4      
#> [17] mgcv_1.9-4         scales_1.4.0       jquerylib_0.1.4    reformulas_0.4.1  
#> [21] Rdpack_2.6.4       cli_3.6.5          rlang_1.1.6        rbibutils_2.3     
#> [25] KFAS_1.6.0         splines_4.5.3      withr_3.0.2        cachem_1.1.0      
#> [29] yaml_2.3.10        tools_4.5.3        nloptr_2.2.1       minqa_1.2.8       
#> [33] tsibble_1.2.0      boot_1.3-32        vctrs_0.6.5        R6_2.6.1          
#> [37] clubSandwich_0.6.1 zoo_1.8-14         lifecycle_1.0.4    lubridate_1.9.4   
#> [41] MASS_7.3-65        pkgconfig_2.0.3    pillar_1.11.1      bslib_0.9.0       
#> [45] gtable_0.3.6       glue_1.8.0         Rcpp_1.1.0         xfun_0.53         
#> [49] tibble_3.3.0       tidyselect_1.2.1   knitr_1.50         farver_2.1.2      
#> [53] htmltools_0.5.8.1  nlme_3.1-168       rmarkdown_2.29     labeling_0.4.3    
#> [57] compiler_4.5.3     S7_0.2.0

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.