# Visualization in tidyILD

## Role of visual inspection

Intensive longitudinal data (ILD) benefits from layered plots: raw trajectories, spacing and missingness, within/between structure, model-based residuals, and (when fitted) heterogeneity of person-specific parameters. tidyILD spreads these across `ild_plot()`, `ild_autoplot()` on diagnostics bundles, and backend-specific helpers (KFAS, TVEM, circadian). There is no single `ild_visualize()`; use the table below as an index.

## Map: question → function → bundle section (if any)

Question | Primary API | Notes
--- | --- | ---
Spaghetti trajectories | `ild_spaghetti()`, `ild_plot(..., type = "trajectory")` | `max_ids`, `time_var`, optional `facet_by`
Person × time heatmap | `ild_heatmap()`, `ild_plot(..., type = "heatmap")` | Optional `facet_by` for clusters
Spacing / intervals | `ild_plot(..., type = "gaps")`, `ild_autoplot(bundle, section = "design", type = "coverage")` | `ild_spacing()` is tabular + AR1/CAR1 hint
Missingness pattern | `ild_plot(..., type = "missingness")`, `ild_missing_pattern()$plot` | Bundle: `section = "data", type = "missingness"`
Within/between densities | `ild_center_plot()`, `ild_decomposition(..., plot = TRUE)` | Not marginal effects of fitted model
Residual ACF | `ild_plot(fit, type = "residual_acf")`, `ild_autoplot(bundle, section = "residual", type = "acf")` | Sequence-based lag; see `?ild_acf`
Obs vs fitted scatter | `ild_plot(fit, type = "fitted")` |
Obs vs fitted over time | `ild_plot_predicted_trajectory(fit)`, `ild_plot(..., type = "predicted_trajectory")` | Two lines per id
Person-specific / partial pooling | `ild_autoplot(h, type = "caterpillar")` on `ild_heterogeneity()`; bundle `section = "fit", type = "heterogeneity"` |
Time-varying effect | `ild_tvem_plot()` | After `ild_tvem()`
State space / continuous time | `ild_plot_states()`, `ild_plot_forecast()`, `ild_plot_filtered_vs_smoothed()` on `ild_kfas()` fits; `ild_autoplot` for ctsem where supported | Optional KFAS / ctsem
Diurnal pattern | `ild_circadian()` |

After `ild_diagnose()`, prefer `ild_autoplot(bundle, ...)` for a consistent section layout (`residual`, `fit`, `predictive`, `data`, `design`, `causal`).

## Example: spaghetti, predicted trajectories, facet by cluster

    library(tidyILD)
    set.seed(1)
    d <- ild_simulate(n_id = 24, n_obs_per = 10, seed = 1)
    d$cluster <- rep(LETTERS[1:3], length.out = nrow(d))
    x <- ild_prepare(d, id = "id", time = "time")
    ild_spaghetti(x, var = "y", facet_by = "cluster", max_ids = 12L)

    fit <- ild_lme(y ~ 1 + (1 | id), data = x, ar1 = FALSE, warn_no_ar1 = FALSE, warn_uncentered = FALSE)
    ild_plot_predicted_trajectory(fit, time_var = ".ild_seq", max_ids = 8L, facet_by = "cluster")

## Recipe: facet panels without a dedicated helper

Any ggplot from `ild_*` can be stored and extended (e.g. `p + facet_wrap(vars(week))`) if you add a column to the ILD first. The `facet_by` argument on `ild_plot()` passes through to `ggplot2::facet_wrap()` for trajectory, heatmap, gaps, and predicted trajectories.

## Partial effects for `_wp` and `_bp` (external packages)

tidyILD does not reimplement marginal effects. After `ild_center()`, fit with `y ~ x_wp + x_bp + (1|id)` and use marginaleffects or ggeffects on the fitted object. Keep the estimand explicit: slopes on `x_wp` are within-person associations; `x_bp` captures between-person differences in level.

    # install.packages(c("marginaleffects", "ggeffects"))  # if needed
    x <- ild_center(x, x)
    fit <- ild_lme(y ~ x_wp + x_bp + (1 | id), data = x, warn_uncentered = FALSE)
    # Example (syntax may vary by package version):
    # marginaleffects::plot_predictions(fit, condition = "x_wp")
    # marginaleffects::plot_predictions(fit, condition = "x_bp")
    # ggeffects::ggpredict(fit, terms = "x_wp")  # then plot() or ggplot2 layer

## See also

`vignette("tidyILD-workflow", package = "tidyILD")`, `vignette("ild-decomposition-and-spacing", package = "tidyILD")`, `?ild_plot`, `?ild_autoplot`.