Author: Alex Litovchenko
Date: 2026-04-17

# Short analysis report

#### Alex Litovchenko

#### 2026-04-17

This vignette shows a minimal analysis report: fit a model, print fixed effects, plot fitted vs observed, and show residual ACF and Q-Q.

## 1. Fit model(s)

    library(tidyILD)
    d <- ild_simulate(n_id = 8, n_obs_per = 10, irregular = TRUE, seed = 101)
    x <- ild_prepare(d, id = "id", time = "time", gap_threshold = 7200)
    x <- ild_center(x, y)
    fit <- ild_lme(y ~ y_bp + y_wp + (1 | id), data = x, ar1 = FALSE, warn_no_ar1 = FALSE)
    #> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
    #> Model failed to converge with max|grad| = 0.117947 (tol = 0.002, component 1)
    #> Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
    #>  - Rescale variables?

## 2. Tidy fixed-effects table

    tidy_ild_model(fit)
    #> # A tibble: 3 × 18
    #>   term    component effect_level estimate std_error conf_low conf_high statistic
    #>   <chr>   <chr>     <chr>           <dbl>     <dbl>    <dbl>     <dbl>     <dbl>
    #> 1 (Inter… fixed     population   9.93e-17  2.69e-17 4.65e-17  1.52e-16   3.69e 0
    #> 2 y_bp    fixed     between      1   e+ 0  2.72e-17 1   e+ 0  1   e+ 0   3.68e16
    #> 3 y_wp    fixed     within       1   e+ 0  5.29e-17 1   e+ 0  1   e+ 0   1.89e16
    #> # ℹ 10 more variables: p_value <dbl>, interval_type <chr>, engine <chr>,
    #> #   model_class <chr>, rhat <dbl>, ess_bulk <dbl>, ess_tail <dbl>, pd <dbl>,
    #> #   rope_low <dbl>, rope_high <dbl>

With cluster-robust standard errors (requires the clubSandwich package):

    tidy_ild_model(fit, se = "robust", robust_type = "CR2")
    #> # A tibble: 3 × 18
    #>   term  component effect_level estimate std_error   conf_low conf_high statistic
    #>   <chr> <chr>     <chr>           <dbl>     <dbl>      <dbl>     <dbl>     <dbl>
    #> 1 (Int… fixed     population   9.93e-17  1.36e-16 -1.68 e-16  3.67e-16  7.28e- 1
    #> 2 y_bp  fixed     between      1   e+ 0  2.01e-16  1.000e+ 0  1   e+ 0  4.97e+15
    #> 3 y_wp  fixed     within       1   e+ 0  9.16e-18  1    e+ 0  1   e+ 0  1.09e+17
    #> # ℹ 10 more variables: p_value <dbl>, interval_type <chr>, engine <chr>,
    #> #   model_class <chr>, rhat <dbl>, ess_bulk <dbl>, ess_tail <dbl>, pd <dbl>,
    #> #   rope_low <dbl>, rope_high <dbl>

## 3. Fitted vs observed

    ild_plot(fit, type = "fitted")

## 4. Residual diagnostics: ACF and Q-Q

    diag <- ild_diagnostics(fit, type = c("residual_acf", "qq"))
    diag
    #> ILD diagnostics
    #>   Engine: lmer
    #>   AR1/CAR1: no
    #>   Id column: id  Time column: time
    #>   N persons: 8  N observations: 80
    #>   Types computed: residual_acf, qq

    plots <- plot_ild_diagnostics(diag)
    plots$residual_acf
    plots$qq

## With AR1 (nlme)

Same workflow with residual autocorrelation (nlme path). If the AR1 model fails to converge on this small example, we show the code only; in practice use more data or a different seed.

    fit_ar1 <- tryCatch(
      ild_lme(y ~ y_bp + y_wp, data = x, random = ~ 1 | id, ar1 = TRUE),
      error = function(e) NULL
    )
    if (!is.null(fit_ar1)) {
      tidy_ild_model(fit_ar1)
    } else {
      message("AR1 fit did not converge on this run; use ild_lme(..., ar1 = TRUE) with your data.")
    }
    #> AR1 fit did not converge on this run; use ild_lme(..., ar1 = TRUE) with your data.

    if (!is.null(fit_ar1)) {
      diag_ar1 <- ild_diagnostics(fit_ar1, type = c("residual_acf", "qq"))
      diag_ar1
    }

## Time-varying effects (TVEM)

When the effect of a predictor may change over time (e.g. stronger in the morning), use `ild_tvem()` to fit a GAM with a smooth in time and a time-varying coefficient. The plot shows how the effect of the predictor varies over the study timeline; interpret the curve as the estimated effect at each time point (with uncertainty band).

    set.seed(101)
    d2 <- ild_simulate(n_id = 6, n_obs_per = 12, seed = 101)
    d2$x <- rnorm(nrow(d2))
    x2 <- ild_prepare(d2, id = "id", time = "time")
    tv <- ild_tvem(x2, "y", "x", k = 5, re_id = TRUE)
    ild_tvem_plot(tv)