--- title: "chestR workflow: global Cox to local biomarker maps" author: "Richard Jackson" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{chestR workflow: global Cox to local biomarker maps} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 4.5 ) ``` ## Overview **chestR** re-fits a Cox model at each point on a biomarker grid using kernel weights. Local coefficients show how treatment (and other) effects vary across biomarker space. The usual workflow is: 1. Fit a global Cox model. 2. Call `chestr()` on biomarker values. 3. Visualise a coefficient with `plot()` / `plot.chestr()`. 4. Optionally run `chestr_test()` for a permutation global test. This vignette uses a small simulated survival dataset so it builds without external files. ## Simulate data and fit a global Cox model ```{r simulate} library(survival) library(chestR) set.seed(20250806) n <- 120 dat <- data.frame( trt = rbinom(n, 1, 0.5), cov = rnorm(n), biom1 = rnorm(n), biom2 = rnorm(n) ) # Mild treatment-effect modification near the origin of biomarker space lp <- 0.2 * dat$cov + log(0.7) * dat$trt * exp(-0.5 * (dat$biom1^2 + dat$biom2^2)) dat$time <- rexp(n, rate = exp(lp)) dat$status <- as.integer(dat$time < 4) dat$time[dat$status == 0L] <- 4 base <- coxph(Surv(time, status) ~ trt + cov, data = dat) summary(base)$coefficients ``` ## Local estimates with `chestr()` ```{r chestr} biom <- dat[, c("biom1", "biom2")] cr <- chestr( base, biom, grid.size = 8, method = "legacy", kern.adj = 2, min_events_per_df = 5 ) cr head(cr$estimates[, c("biom1", "biom2", "trt", "ess_events", "events_per_df", "reliable")]) ``` The object has class `"chestr"` and stores: - `cr$estimates` — local coefficients, SEs, ESS / reliability columns - `cr$base` — the global Cox model - `cr$biom` — biomarker data used for weighting and plotting ## Plot local treatment effects ```{r plot} plot(cr, trt.param = "trt", col.scale = "obs", reliable_only = TRUE) ``` `plot.chestr()` takes everything it needs from `cr` (`base` and `biom` are not passed again). By default only reliable grid points are drawn. ## Permutation global test Pointwise local estimates from `chestr()` are descriptive. Formal evidence that the local treatment surface is not flat can be assessed with `chestr_test()`, which permutes treatment labels and recomputes `T_L2` and `T_MAX`. ```{r test, eval = FALSE} cr <- chestr( base, biom, grid.size = 8, method = "legacy", kern.adj = 2, min_events_per_df = 5, treat_term = "trt" ) # data, treat_term, and fit settings come from cr: tst <- chestr_test(cr, B = 99, seed = 1) tst ``` ## Session info ```{r session} sessionInfo() ```