---
title: "Temporal dynamics: choosing a model for ILD"
author: "tidyILD authors"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Temporal dynamics: choosing a model for ILD}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 6,
  fig.height = 4
)
```

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

- **Irregular spacing** makes **index lags** (row order) easy to misinterpret as equal time. Prefer **`gap_aware`** or **`time_window`** in `ild_lag()`, or align to a grid, or use **continuous-time** models when the estimand requires it (`vignette("kfas-irregular-timing-spacing", package = "tidyILD")`).
- **Residual ACF** after a lag-mean model may indicate **unmodeled autocorrelation**; compare to **`ild_lme(..., ar1 = TRUE)`** (nlme path with AR1 or CAR1 chosen from spacing). See `vignette("temporal-dynamics-model-choice", package = "tidyILD")` guardrails in `ild_diagnose()`.

## 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

```{r minimal-crosslag}
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)
out$lag_term[, c("term", "estimate", "std_error")]
```

```{r minimal-ar1, eval = requireNamespace("nlme", quietly = TRUE)}
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"
}
```

```{r minimal-tvem}
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)
```

## Further reading

- `vignette("tidyILD-workflow", package = "tidyILD")`
- `vignette("ild-specialist-backends", package = "tidyILD")` (multivariate / high-p handoffs)
- `vignette("kfas-choosing-backend", package = "tidyILD")`
- `vignette("brms-dynamics-recipes", package = "tidyILD")` (Bayesian templates)
- `vignette("heterogeneity-interpretation", package = "tidyILD")` (person-specific slopes vs dynamics)

```{r session-info, echo = FALSE}
sessionInfo()
```
