While classical models like the Cox Proportional Hazards model are highly interpretable, they rely on strict assumptions of linear, additive effects. Random Survival Forests (RSF) overcome this by building a non-linear ensemble of decision trees.
In this tutorial, we will demonstrate how to run a standalone RSF
using SuperSurv’s unified wrappers, evaluate its individual
performance, and finally include it in a Super Learner ensemble.
This teaching example uses 200 sampled patients, 50 trees, and three cross-validation folds to keep it quick to run. These settings illustrate the workflow rather than provide a full-data performance comparison.
library(SuperSurv)
library(survival)
data("metabric", package = "SuperSurv")
set.seed(123)
metabric <- metabric[sample(seq_len(nrow(metabric)), 200), ]
train_idx <- sample(1:nrow(metabric), 0.7 * nrow(metabric))
train <- metabric[train_idx, ]
test <- metabric[-train_idx, ]
X_tr <- train[, grep("^x", names(metabric))]
X_te <- test[, grep("^x", names(metabric))]
new.times <- seq(50, 200, by = 25) SuperSurv provides unified wrappers that automatically
handle the training and standardization of survival probabilities. You
can use these completely independent of the Super Learner ensemble.
# 1. Fit the standalone wrapper
rf_standalone <- surv.rfsrc(
time = train$duration,
event = train$event,
X = X_tr,
new.times = new.times,
ntree = 50
)
# 2. Extract the fitted model object and prediction matrix
rf_fit <- rf_standalone[["fit"]]
rf_pred_matrix <- rf_standalone[["pred"]]Because our plotting functions are universally compatible, we can plot individual patient curves directly from this standalone matrix:
Plotting examples run only when both randomForestSRC and
the optional ggplot2 package are installed.
# Plot the first 3 patients in our training set
plot_predict(preds = rf_pred_matrix, eval_times = new.times, patient_idx = 1:3)We can also pass this standalone model directly into our evaluation suite to test its performance on new data.
# The function automatically detects this is a single model and plots it!
plot_benchmark(
object = rf_fit,
newdata = X_te,
time = test$duration,
event = test$event,
eval_times = new.times
)While the standalone RSF is powerful, we can objectively evaluate if
it outperforms classical models by putting them together in a
SuperSurv ensemble.
rf_library <- create_grid("surv.rfsrc", list(ntree = 50))
my_library <- c("surv.coxph", "surv.weibull", rf_library)
fit_supersurv <- SuperSurv(
time = train$duration,
event = train$event,
X = X_tr,
newdata = X_te,
new.times = new.times,
event.library = my_library,
cens.library = c("surv.coxph"),
control = list(
saveFitLibrary = TRUE,
event.t.grid = seq(0, max(train$duration[train$event == 1]), length.out = 30),
cens.t.grid = seq(0, max(train$duration[train$event == 0]), length.out = 30)
),
verbose = FALSE,
nFolds = 3
)When we pass the SuperSurv ensemble into the exact same
benchmark function, it automatically unpacks the library and plots the
ensemble against all its constituent models.
plot_benchmark(
object = fit_supersurv,
newdata = X_te,
time = test$duration,
event = test$event,
eval_times = new.times
)Including flexible learners broadens the candidate library and may improve adaptation to nonlinear or non-proportional-hazards structure. Their contribution is determined by the selected cross-validated objective and should be evaluated on held-out data.