nbsurv Workflow

Overview

nbsurv implements a conditional naive Bayes model for right-censored survival data. At each prediction horizon, the method treats survival past the horizon as a binary classification problem and combines:

The package also includes utilities for horizon-specific evaluation, cross-validation, and hyper-parameter tuning.

Fit a model

library(nbsurv)
library(survival)

lung <- stats::na.omit(lung)
lung$status <- as.integer(lung$status == 2)

fit <- nbsurv(
  Surv(time, status) ~ age + sex + ph.ecog,
  data = lung
)

fit
#> nbsurv conditional naive Bayes model
#> Formula: Surv(time, status) ~ age + sex + ph.ecog
#> Training rows: 167 
#> Predictors: age, sex, ph.ecog 
#> Prediction grid size: 110 
#> Covariance structure: diagonal

Generate predictions

times <- c(100, 200, 400, 800)

surv_pred <- predict(
  fit,
  newdata = lung[1:5, ],
  times = times
)

event_pred <- predict(
  fit,
  newdata = lung[1:5, ],
  times = times,
  type = "event"
)

surv_pred
#>       t_100     t_200     t_400      t_800
#> 2 0.8385794 0.7174790 0.4493185 0.08609771
#> 4 0.9186537 0.7076650 0.3810991 0.08243387
#> 6 0.7470443 0.4274068 0.2517857 0.05200281
#> 7 0.8007149 0.6915579 0.4054933 0.05016755
#> 8 0.6763963 0.5337570 0.2746157 0.04845473
event_pred
#>        t_100     t_200     t_400     t_800
#> 2 0.16142060 0.2825210 0.5506815 0.9139023
#> 4 0.08134627 0.2923350 0.6189009 0.9175661
#> 6 0.25295575 0.5725932 0.7482143 0.9479972
#> 7 0.19928506 0.3084421 0.5945067 0.9498324
#> 8 0.32360365 0.4662430 0.7253843 0.9515453

The returned survival matrix is post-processed to be monotone in time.

Evaluate the fitted model

metrics <- evaluate_nbsurv(
  fit,
  newdata = lung,
  times = times
)

metrics
#>   time      brier concordance
#> 1  100 0.12490246   0.5176070
#> 2  200 0.22995788   0.5055850
#> 3  400 0.24545110   0.4982014
#> 4  800 0.07145922   0.5127793

evaluate_nbsurv() reports horizon-specific IPCW Brier scores and concordance values.

Cross-validation

cv_fit <- cv_nbsurv(
  Surv(time, status) ~ age + sex + ph.ecog,
  data = lung,
  folds = 3,
  times = times,
  seed = 1
)

cv_fit$summary
#>   time      brier concordance
#> 1  100 0.12339477   0.5029725
#> 2  200 0.23058672   0.4899689
#> 3  400 0.26832337   0.4907712
#> 4  800 0.07500398   0.4666922

Tune hyper-parameters

grid <- data.frame(
  scale = c(TRUE, FALSE),
  laplace = c(1, 2),
  min_sd = c(0.05, 0.10)
)
grid$time_grid <- I(list(NULL, NULL))

tuned <- tune_nbsurv(
  Surv(time, status) ~ age + sex + ph.ecog,
  data = lung,
  param_grid = grid,
  folds = 3,
  times = c(100, 200, 400),
  seed = 1
)

tuned$results
#>   scale laplace min_sd time_grid mean_metric
#> 1  TRUE       1   0.05             0.2074350
#> 2 FALSE       2   0.10             0.3655025
tuned$best_params
#>   scale laplace min_sd time_grid mean_metric
#> 1  TRUE       1   0.05              0.207435

Plot fitted curves

plot(fit, times = c(100, 200, 400), n_curves = 3)