Skip to content

Add interval-censored survival support via multiple imputation#291

Closed
fabian-s wants to merge 3 commits into
adibender:masterfrom
fabian-s:ic-mi-upstream
Closed

Add interval-censored survival support via multiple imputation#291
fabian-s wants to merge 3 commits into
adibender:masterfrom
fabian-s:ic-mi-upstream

Conversation

@fabian-s

Copy link
Copy Markdown
Collaborator

Summary

Adds support for interval-censored time-to-event data via a multiple-imputation (MI) workflow. Surv(L, R, type = "interval2") responses are detected automatically by as_ped(); the new fitters repeatedly draw exact event times from the model-based conditional hazard on (L, R], re-fit the standard right-censored PAMM pipeline on each completed data set (one shared cut grid, so fits are poolable), and pool inference with Rubin's rules.

The workflow was validated in a 39-cell × 500-replication Monte Carlo benchmark (ADEMP design; oracle / midpoint-imputation / icenReg ic_par + ic_sp / Turnbull comparators). The benchmark materials are deliberately not part of this PR; they live in the fork under attic/ic-benchmark/ (design, decision log, and full report) if you want to inspect them.

What's included

Fitters

  • pamm_ic() (single event) and pamm_ic_cr() (competing risks; retains observed causes, imputes unknown ones from the fitted cause-specific hazards). Imputation is always proper: coefficients are drawn from the imputation model's asymptotic posterior before each draw.
  • iter argument (default 1): chained refit-and-reimpute within each imputation chain. One-step MI is biased for early-time survival when inspection intervals are wide (benchmark: coverage falls with n); iter = 3 removes most of that bias at ~linear fit cost. Documented recommendation: default for densely inspected data, iter = 3 for sparse panels.
  • warn_unstable_chains(): flags numerically degenerate imputation chains (a silent mgcv failure mode that can occur when iterating flexible time-varying models on small samples) via a warning and $unstable_chains.

Pooled inference

  • print()/summary() report the pooled fit: Rubin-combined coefficients/covariances, median-p term tests, fraction-of-missing-information diagnostics.
  • add_hazard(), add_cumu_hazard(), add_surv_prob(), add_cif() gain pamm_ic methods that combine per-imputation posterior draws (each fit evaluated with its own design matrix, since mgcv bases are data-dependent), so intervals carry within- plus between-imputation uncertainty. add_cumu_hazard()/add_surv_prob() are converted to S3 generics with default methods (backward compatible).
  • Per-imputation fits are stored slimmed (strip_pamm_fit()), so memory does not scale with m.

Supporting changes

  • R/as-ped-ic.R / R/impute-ic.R: IC detection/parsing/transformation and the conditional-hazard imputation sampler (calibration unit-tested: PIT uniformity, draws respect (L, R]).
  • add_inspections() (R/sim-ic.R): manufactures IC panel data from exact simulated times for examples/testing. Uses a coherent end-of-study-examination censoring convention (terminal_exam) — mixing exact exit times for survivors with open intervals for undetected events would make right-censoring informative and bias every IC likelihood (regression-tested).
  • sim_pexp(): now factor-safe — bare factor arithmetic in the formula errors loudly instead of silently coercing to NA.
  • resolve_rhs_vars() helper in R/formula-utils.R (dot-formula resolution, used by the IC pipeline).
  • Vignette interval-censored.Rmd: worked single-event and competing-risks examples, guidance on choosing m (via FMI) and iter, comparison against midpoint imputation and the Turnbull NPMLE.
  • Tests: test-interval-censored.R (+ a sim_pexp factor-safety test); full package suite passes (688 assertions).

Notes for review

  • Exact-only data through the IC entry points reproduces the plain right-censored PAMM exactly (tested).
  • Recurrent-event / general multi-state interval censoring is out of scope (imputing one transition time changes the next at-risk window, so draws must be joint along each path) — noted in the vignette as a planned extension.
  • This PR is intentionally isolated from my other open work (gg_smooth/get_terms refactor etc.); only IC-related changes are included.

🤖 Generated with Claude Code

Interval-censored Surv(L, R, type = "interval2") responses are detected
and handled by a proper-MI workflow: exact event times are repeatedly
drawn from the model-based conditional hazard (coefficients drawn from
the imputation model's posterior), each completed data set is re-fit as
a PAMM on one shared cut grid, and inference is Rubin-pooled
(print/summary with median-p and FMI diagnostics; pooled add_hazard /
add_cumu_hazard / add_surv_prob / add_cif).

- pamm_ic() (single event) and pamm_ic_cr() (competing risks, incl.
  imputation of unknown causes)
- iter argument: chained refit-and-reimpute per imputation chain;
  removes the one-step early-time survival bias under sparse inspection
  (validated in a 39-cell x 500-rep Monte Carlo benchmark; recommended
  iter = 3 for sparse panels, default 1)
- warn_unstable_chains(): flags numerically degenerate imputation
  chains (silent mgcv failure mode under flexible TV terms + small n)
- add_inspections() simulation helper with a coherent end-of-study-exam
  censoring convention (terminal_exam; avoids an informative-censoring
  trap) for IC examples and validation
- sim_pexp() made factor-safe (errors loudly on bare factor arithmetic
  instead of silently coercing to NA)
- vignette (interval-censored.Rmd) with worked examples, guidance on m
  and iter, comparison against midpoint imputation and Turnbull
- comprehensive test suite (test-interval-censored.R); full package
  suite passes (688 assertions)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 12, 2026 10:56

This comment was marked as outdated.

fabian-s and others added 2 commits June 12, 2026 13:14
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit e20bb60)
@fabian-s

Copy link
Copy Markdown
Collaborator Author

simulation study for this:
report.html

especially with iterated MI, this seems to work quite well for both point and interval estimates...

@fabian-s

Copy link
Copy Markdown
Collaborator Author

suggested vignette for this:
interval-censored.html

@fabian-s

Copy link
Copy Markdown
Collaborator Author

see #292

@fabian-s fabian-s closed this Jun 17, 2026
fabian-s added a commit that referenced this pull request Jun 17, 2026
Consolidated PRs #284, #287, #289, #290, #291 and consistent t=0 boundary rows, shared simulation draws, and S3 dispatch fixes for `add_*` functions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants