cv() and holdout(): a strata column that is not in the data now gives a
warning instead of being silently dropped (the resampling is then not
stratified). The default strata = "status" already stratifies on the event
column of the formula whatever its name (for example cens); the docs now
say so.listlearners(): the docs now say that a learner with tunable = FALSE,
such as "fastgbm", can still be tuned with tune(grid = ).| Old | New |
|---|---|
| list_survlearners() | listlearners() |
| list_metrics() | listmetrics() |
| list_interpretability_methods() | listmethods() |
| group_cv() | groupcv() |
as_basetable() to asbasetable().predict(), evaluate() and the other verbs now accept times = 0 (S(0) = 1) in
the grid; times must be finite and non-negative. The rpsurv learner fills
S(0) = 1 itself because it models log time.listlearners(),
listmetrics(), listmethods() and groupcv() replace
list_survlearners(), list_metrics(), list_interpretability_methods()
and group_cv(). The old names still work with a deprecation warning and
will be removed in the next release.coxph predicts with strata() in the formula (one curve per row).aftgee fits training data with missing covariates; its default
prediction times come from the training data.ranger passes case.weights to the engine.blackboost keeps mboost's unrestricted tree tests; trees were stopped
early by a Bonferroni test.survsvm stores the correct outcome column names.densemlp reads its exact time grid; large times were rounded to four
digits.survmetalearner uses equal weights when NNLS returns all zeros instead
of producing NaN.plot() of a tuning result draws one line per value of the second tuned
parameter instead of joining all configurations."aftgee" predictions now use the semiparametric baseline of the AFT
model: the Kaplan-Meier estimate of the censored residuals
log(T) - x'beta, read at log(t) - x'beta. They previously assumed a
log-normal error with scale fixed at 1, which miscalibrated survival: on
the Rotterdam breast cancer data, mean predicted 5-year survival fell from
0.47 to 0.44 against a Kaplan-Meier estimate of 0.44."bart" predictions between the learner's coarse time-grid points are now
interpolated on the log-survival scale, as for "densemlp" in 2.2.1,
instead of holding the value from the start of the interval."densemlp" predictions between the learner's coarse time-grid points are
now interpolated on the log-survival scale (a constant hazard within each
bin) instead of holding the value from the start of the bin. With the
default 10 bins the old lookup overstated survival by up to one bin: on the
Rotterdam breast cancer data, mean predicted 5-year survival fell from
0.54 to 0.42 against a Kaplan-Meier estimate of 0.44.Removed functions that the verbs replace: benchmark(),
benchmark_default_survlearners(), benchmark_tuned_survlearners(),
summarise_benchmark(), summarize_benchmark_results(),
best_survlearner() and plot_benchmark() (use compare()),
estimate_rmst() and plot_rmst() (use estimate()),
cv_survmetalearner() (use evaluate(model = "survmetalearner")),
plot_survmetalearner_weights(), compute_shap_mean() (use
interpret(method = "shap")), plot_survcurve() (use kmplot()) and
screen_fdr() (use the "selectcox" or "glmnet" learners).
New kmplot(): Kaplan-Meier curves in a publication style, with censoring
marks, an optional log-rank p-value, optional confidence bands and a
number-at-risk table coloured by group. type draws the survival function,
the risk function (one minus survival), the cumulative hazard, or the
log(-log) survival against log time for checking proportional hazards.
A factor status gives the Aalen-Johansen cumulative incidence of the chosen
event under competing risks. A fitted model adds its curves, dashed:
the mean prediction within each group (model.curve = "predicted", a
calibration check) or covariate-adjusted curves by G-computation
(model.curve = "adjusted"). Panels combine with 'patchwork' operators.
survalis now requires 'ggplot2' 3.5.0 or later.
These change results; rerun analyses made with earlier versions.
Outcome handling: Surv() arguments must now be column names. A computed
time or status (Surv(time / 365, status)) was silently read from the raw
column and is now an error. A 1/2 or logical status (as in
survival::lung) and a status == k recoding now reach every learner and
metric as a 0/1 event. fit() drops incomplete rows once, and ~ .
works in fit(), predict(), estimate() and the explanation methods.
Metrics: the C-index now equals survival::concordance(), and the AUC
weights cases by the censoring survival just before their event time, as
in 'timeROC'. The IBS no longer depends on the order of times; IAE and
ISE integrate over the evaluation window only. Metric values are stored at
full precision (rounding happens only when printing), the standard error
counts only non-missing splits, and unknown metric names, or single-time
metrics given several times, are rejected before any model is fitted.
Resampling: each split gets its own seed, so evaluate(), compare() and
tune() give the same values on repeated runs and whatever ncores is.
tune() keeps engine arguments passed in ... in the best spec and
rejects an argument that is both tuned and fixed.
Cox-type predictions: "coxph" now uses survival::survfit(), and the
penalized Cox learners use a Breslow baseline on the training linear
predictor. The earlier baseline was too large when the mean linear
predictor was far from 0.
Explanations: interpret(method = "shap") uses a permutation estimator
whose values add up to the prediction gap; "ale" follows Apley and Zhu
(2020), using only the observations inside each bin; "interactions"
computes the centred Friedman-Popescu H statistic; "varimp" scores the
fixed model on permuted data and reports a positive importance when
permuting a feature makes predictions worse, whatever the metric's
direction. Calibration uses newdata when given and handles tied
predictions. "shap", "counterfactual" and "surrogate" require a
one-row newdata, and the explanation methods use only the model's own
predictors.
Learners:
"rsf", "ranger", "cforest",
"bart", "blackboost", "densemlp") read their curves as step
functions, equal to 1 before the first time."rpart" uses the Kaplan-Meier curve of each leaf."nbsurv" predicts each row on its own, avoiding an engine bug in batch
prediction."rsf" follows set.seed()."survmetalearner" stacks on subjects with known status at each
landmark, with censoring weights."xgboost" with objective = "survival:cox" codes censored times as
xgboost expects and uses a Breslow baseline. With "survival:aft" it
starts from the geometric mean time."bart" passes ... to BART::surv.bart()."selectcox" carries survival forward past the last follow-up.The design-matrix learners ("glmnet", "coxboost", "xgboost",
"aalen", "aftgee") keep the training factor levels, so a single row
or a test fold missing a level is coded correctly, and newdata no
longer needs the outcome columns.
kmplot(model = ) accepts a model fitted on a rescaled time (days versus
years) and warns when the model does not use the grouping variable.
survalis is now built around seven verbs: fit(), predict(),
evaluate(), tune(), compare(), interpret() and estimate(). The
exported API is these verbs plus the resampling specs (cv(), holdout(),
group_cv(), bootstrap()), the lookups (list_survlearners(),
list_metrics(), list_interpretability_methods()), Surv() and the
veteran data. The granular layer is no longer exported: fit_*(),
predict_*(), tune_*(), cv_survlearner(), cv_summary(), cv_plot(),
score_survmodel(), compute_*(), plot_*(), the *_survmat() metrics,
brier(), survmat_to_*(), default_times(),
list_tunable_survlearners(), theme_survalis() and the colour scales.
vignette("from-1.0") maps each one to its verb.
Table operations inside survalis (reshaping, grouped summaries, row
binding, sorting and merging) now use 'basetable' instead of base R.
Result tables stored in fitted objects (evaluate(), compare(),
interpret(), estimate()) are basetable objects; as.data.frame() on a
survalis result still returns a plain data.frame.
New decision-weighted scores (dwscore()): the loss of the rule "act if
predicted risk exceeds c", averaged over risk thresholds c with a stated
weight (threshold range, SurvAcc, Brier, logarithmic or Beta), with IPCW for
censoring. Each score is a weighted area under the net benefit curve. The
metric ids "survacc" and "range:<lower>-<upper>" (for example
"range:0.05-0.20") work in evaluate(), compare() and tune().
The "brier" and "ibs" metrics now use the same censoring weights as
dwscore() and the usual IPCW Brier score (Graf et al. 1999): events at or
before t are weighted by 1 / G(T-). Values can change in the fourth
decimal.
The decision curve (interpret(method = "dca")) now uses the same
censoring weights, treats a patient when predicted risk is above the
threshold (not equal to it), and computes "treat all" from the same weights
instead of the Kaplan-Meier risk. Each "range:<lower>-<upper>" loss then
equals the weighted area between the treat-all and model curves exactly.
Custom learners: model in every verb also accepts
list(fit = function(formula, data, ...), predict = function(object, newdata, times)),
where predict returns an nrow(newdata) x length(times) matrix of
survival probabilities. compare() accepts a list mixing ids and custom
learners.
evaluate(fit, newdata = test) scores a fitted learner on new data
(external or temporal validation), and evaluate(S, y = Surv(time, status))
scores a survival matrix produced anywhere.
as.data.frame() also works on a fit() result (one row: model,
engine, formula, n, events; it was an error), and
as.data.frame(predict(...), format = "long") gives one row per
observation and time (id, time, value). The estimate() result and
its summary name the interval bounds conf_low and conf_high (were
conf.low and conf.high).
tune() works for any learner when you supply grid: configurations are
scored on shared splits under any resampling spec. Learners listed by
list_survlearners(has_tune = TRUE) keep their built-in default grids.
A grid passed to tune() no longer has to name every parameter of a
learner's built-in tuner. A grid that left one out (for example
grid = data.frame(cp = c(0.001, 0.01)) for "rpart") stopped with
'argument "maxdepth" is missing'. Parameters not in the grid now take the
learner's defaults: such a grid, or one with extra engine arguments, is
scored on shared splits like the grid of any other learner, and ...
supplies fixed arguments to every configuration. A grid with exactly the
built-in columns still uses the built-in tuner. The "survsvm" and
"glmnet" tuners also take a data frame grid row by row instead of crossing
its columns.
tune() with a built-in default grid returned no configurations for the
"glmnet", "bart", "blackboost", "bnnsurv", "cforest",
"flexsurvreg" and "orsf" learners, and refitted the model with none of
the tuned parameters, so compare(tune = TRUE) silently compared default
fits. Every built-in tuner now returns its scored grid and the refit uses
the best configuration. A configuration that fails now gives a warning
naming the learner and its parameter values and is left out; if every
configuration fails, tune() stops. Before, failed configurations were
dropped without a word, or one failure aborted the whole search.
interpret() gains method = "roc" (time-dependent ROC curve) and
method = "dca" (decision curve), both at one eval_time.
as.data.frame() works on every interpret() result and returns plain
column names. It failed for "survcluster", "roc", "dca" and
"tree_surrogate" ("cannot coerce class ... to a data.frame"), and for
"pdp", "ice", "ale" and "calibration" it pasted the parts of the
result side by side, recycling the shorter ones, under names such as
results.time or integrated.integrated_surv. Now "pdp" and "ice"
give one row per feature value, observation and time (feature,
feature_value, id, time, surv, type), "ale" one row per
feature value and time (feature, feature_value, time, ale),
"calibration" the calibration table with its eval_time,
"survcluster" one row per observation and time (id, cluster,
medoid, time, surv), "roc" and "dca" the curve with its
eval_time, and "tree_surrogate" one row per time and feature (splits,
r_squared). For "pdp" and "ale", as.data.frame(x, what =
"integrated") returns the curve integrated over time (feature,
feature_value, integrated). print() shows the first rows of this
data frame instead of the raw result list.
list_survlearners() now returns learner and tunable only, and
list_interpretability_methods() returns the interpret() method ids with
a one-line summary.
fit() no longer accepts engine arguments through ...; pass them in
spec = list(...). Extra arguments now give an error instead of a warning.
Fewer silent failures. estimate() warns with the number of failed
bootstrap replicates and the first error (and stops if all fail) instead of
quietly building the interval from the rest. fit() reports why it could
not read a formula. The survival super learner gives the error when it
drops a base learner. The blackboost and cforest learners no longer
hide engine warnings; cforest caps mtry at the number of predictors
itself, as 'party' would.
The stpm2 learner is removed: fit_stpm2() and predict_stpm2() are
gone and 'rstpm2' is no longer a dependency. Use fit_rpsurv() /
fit(model = "rpsurv"), which fits the same Royston-Parmar model on the
hazard, odds, or probit scale and adds nonlinear effects (nle).
The orsf tuner passed its min_events grid column to 'aorsf' as
n_split, the number of candidate cut points, not the minimum number of
events. The column is now split_min_events and sets that minimum.
The survsvm learner now has its own engine and no longer depends on
'survivalsvm'. Its "quadprog" path called Matrix::nearPD(), which could
stop with "error code 1 from Lapack routine 'dsyevr'" depending on the
BLAS/LAPACK library. The new engine fits a kernel survival support vector
regression on log time (squared loss for events, one-sided squared loss for
censored times) and solves it exactly by active-set Newton steps with one
Cholesky factorization each, so no quadratic programming solver is needed;
it is 10 to 50 times faster. Survival curves now come from the
Kaplan-Meier estimate of cross-fitted residuals,
S(t | x) = S_e(log t - f(x)), which is calibrated, instead of
exp(-t / f(x)), which assumed an exponential shape and could give
negative times. dist = "lognormal" is new; "exp" and "weibull" remain
available. The clinical kernel ("add_kernel") treats a factor as one
predictor and accepts constant columns, and "poly_kernel" is fixed.
Only type = "regression" is supported (the ranking types give no
survival curve); opt.meth and diff.meth are ignored. The default
gamma.mu is now 0.1 and the tune_survsvm() grid is
c(0.01, 0.1, 1), matched to the new loss scale. The fitted object's
engine is now "survalis".
The rsf learner failed with "formula is incorrectly specified" for a
survival::Surv() outcome, so the survival super learner dropped it. The
rsf, orsf, blackboost, bnnsurv and flexsurvreg model objects also
recorded the wrong time and status column names.
The bnnsurv learner (bagged k-nearest-neighbour Kaplan-Meier) now has its
own engine and no longer depends on 'bnnSurvival', which is unmaintained.
'bnnSurvival' predicted through parallel::mclapply(), and forking a session
whose multithreaded BLAS (e.g. MKL) is already running could hang
predict_bnnsurv(). The new engine runs in the current process and also:
one-hot encodes factors (they were integer codes inside the Mahalanobis
distance) and matches new data to the training levels; uses the
pseudo-inverse covariance, so constant or collinear columns in a bootstrap
sample are handled; draws feature subsets from all predictors (a factor
counts as one); splits weight equally between neighbours tied at the k-th
distance, so results no longer depend on row order; and reads predictions
at arbitrary times off the step function instead of interpolating
linearly. With numeric predictors and default settings it gives the same
curves as 'bnnSurvival' for the same seed, about ten times faster.
metric = "euclidean" (standardized columns) is new. The fitted object's
engine is now "survalis".
survalis now declares R (>= 4.4.0) and fastgbm (>= 0.7.0). It claimed
R 4.1, but 'fastgbm' up to 0.6.1 needed R 4.5.0 and 'rms' (imported through
'pec') needs R 4.4.0, so installation failed on older R.
Fitting no longer floods the console with warnings. The glmnet learner
passes cox.ties = "breslow", its current default, so 'glmnet' 5.0 does
not warn on every fit (this gave most of the warnings in a tuning or
comparison run). The rpsurv learner muffles the "standard errors
unavailable" warning of 'rpsurv' 0.8.1, since survalis uses only the
predictions. flexsurvreg predictions at a single time no longer warn
about an unknown .pred column.
The survdnn learner is removed, and with it the 'survdnn' and 'torch'
dependencies. 'torch' needs a separate LibTorch download that often failed
to install. Use the densemlp learner (fit(..., model = "densemlp")),
which fits deep survival models with a native C++ backend.
fit_survdnn(), predict_survdnn(), and tune_survdnn() are removed.
survalis no longer defines a plot.formula() method. It replaced
graphics::plot.formula() for every package as soon as survalis was loaded
("Registered S3 method overwritten"). plot_survcurve() is no longer
exported either: for a Kaplan-Meier curve use plot(survival::survfit())
or a dedicated package such as 'ggsurvfit'. plot() on a fit() result
draws the model's predicted survival curves.
Bug fixes found while benchmarking every learner on 31 survival datasets.
fit_ranger() drops predictors that are constant in the data it is fitted on.
With respect.unordered.factors = "order", ranger stopped with "invalid type
(NULL) for variable 'smry$strata'" on a factor with a single level, which
happens in tuning folds of data with many rare binary predictors (metabric).fit_glmnet() and predict_glmnet() accept a single predictor. glmnet stops
with "x should be a matrix with 2 or more columns", so the predictor matrix is
padded with a constant zero column.fit_aalen() standardizes numeric covariates and predict_aalen() applies
the same scaling. timereg::aalen() silently returned an all-zero fit when
covariates were on very different scales, so the predicted survival was 1 for
every subject.predict_flexsurvreg(), predict_bnnsurv(), and predict_cforest() accept a
single evaluation time. A one-time result is now a one-column matrix (it was a
one-row matrix, or a flat table for flexsurvreg), so the single-time metrics
brier and ece can be computed for these learners.fit_survmetalearner() can be called with formula and data only, as
benchmark() and compare() do. It then fits the base learners
(learners, default coxph, glmnet, rsf), builds out-of-fold
predictions, and learns the weights from them. predict_survmetalearner()
interpolates the weights when the requested times differ from the fitted
grid.fit_xgboost() accepts max_depth and eta. tune_xgboost() passed them,
so every configuration failed silently and tune() then stopped with an
unrelated "Unknown columns: ibs".tune() stops with a clear message when every configuration fails during
cross-validation.tune_survsvm() has a default param_grid, and tune_survdnn() accepts its
own default: an argument check rejected the default because missing() is
always true for it.ncores > 1) in compare(),
evaluate(), and cv_survlearner() are now reported. functionals::fmapn()
returns them as try-error objects, which were dropped, so a failure surfaced
as object 'value' not found.data.table -> basetable migration (1.6.1 landed the
shared dt-utils.R choke point; this closes out the rest). All remaining
data.table::data.table()/as.data.table()/rbindlist()/melt()/
dcast()/setorderv()/setcolorder()/copy() calls and bare
[, list(...), by = ...]/:=/.SD/.N grouped expressions across
list_functions.R, plot-survcurve.R, compute_shap.R,
compute_shap_mean.R, compute_varimp.R, compute_pdp.R,
compute_calibration.R, fit_survmetalearner.R, fit_survdnn.R,
fit_bnnsurv.R, fit_coxboost.R, fit_xgboost.R, fit_glmnet.R,
fit_survsvm.R, evaluation.R (cv_summary()), survmat-helpers.R
(plot_survmat()), and benchmark_default_survlearners.R
(summarise_benchmark()/summarize_benchmark_results()/
best_survlearner()) are replaced with base R and
basetable::aggregate()/count()/tolong()/towide()/orderrows()/
applyby(). data.table dropped from Imports entirely. cv_summary()
and score_survmodel() etc. now return plain data.frames instead of
data.tables (no downstream code relied on data.table-specific
semantics). data.table::CJ() grid construction is replaced with base
expand.grid(). All existing tests pass; one test asserting a
"data.table" return class was updated to "data.frame" to match the
new contract..pmap_rbind_dt()/
.map_rbind_dt() helpers (introduced in 1.6.1's basetable migration):
basetable::rbindfill() silently coerces list-columns (e.g. a per-config
vector of hidden-layer sizes) to NA instead of preserving them, unlike
data.table::rbindlist(). No current learner grid combined through these
helpers carries a list-valued hyperparameter, so this was not an active
regression, but it was a landmine for any future one. Both helpers now
route through a new internal .rbind_fill_dt() (base R rbind() after
padding to a common column set), which preserves list-columns and still
handles rows with differing columns (e.g. a failed tuning row that omits
metric columns).R/dt-utils.R internal helpers (.pmap_rbind_dt,
.map_rbind_dt, .complete_cases_df, .wide_metric_row,
.arrange_by_metric_dt, .select_cols) from data.table to basetable
as the row-binding/ordering engine. These helpers are the shared choke
point behind every tuner's parameter-grid results table. Also fixed a
latent single-bracket row-filter in tune_bnnsurv() (results[!results$failed])
that only worked under data.table's DT[i] row-selection semantics;
now explicit (results[!results$failed, ]). data.table remains in use
elsewhere in the package pending further migration.survmat_to_rmst() (and everything built on it: predict(type =
"rmst"), estimate()) previously under-integrated RMST for an off-grid
tau -- it restricted the time grid to times <= tau and summed whole
trapezoidal intervals only, silently dropping the fractional last interval
instead of interpolating into it. For example, on a grid of 0:5, tau =
3.5 returned the same value as tau = 3 (wrong). RMST computation is now
delegated to tvrmst::rmst_dynamic(), with per-subject linear
interpolation to tau on top of its cumulative trapezoidal curve. Values
for tau that already land exactly on a grid point are unchanged; values
for off-grid tau are now correct. tau beyond the last grid point still
holds at the full definite integral (no extrapolation past the observed
curve). Added tvrmst to Imports.nbsurv (conditional naive Bayes survival model, via the
nbsurv package). fit_nbsurv()/predict_nbsurv() added (no tuner).
Registered in list_survlearners(); 24 learners total.rpsurv (Royston-Parmar flexible parametric survival, via the
rpsurv package). fit_rpsurv()/predict_rpsurv() added (no tuner),
restricted cubic splines with optional time-varying covariate effects
(tve) and a choice of scale (hazard/odds/normal). Registered in
list_survlearners(); 23 learners total.funcml package:fit(formula, data, model, spec, seed) -- learner-agnostic fitting;
returns a survalis_fit (a subclass of mlsurv_model, so every existing
helper keeps working on it).predict(fit, newdata, times, type) -- type one of "survival",
"risk", "chf", "hazard" (all returning a validated survmat),
"rmst", "quantile", "median" (numeric).evaluate(fit_or_formula, times, resampling, metrics) -- resampled
performance; a survalis_fit reuses its stored recipe.tune(formula, data, model, grid, resampling, metric) -- grid search,
returns the refit best model as a survalis_fit.compare(formula, data, models, specs, resampling, metrics, tune) --
paired multi-model leaderboard on shared folds.interpret(fit, method, newdata, data, times, ...) -- single entry point
to the compute_* explanation methods, with a plot() that dispatches to
the paired helper.estimate(formula, data, model, estimand, treatment, tau) -- standardised
binary-treatment contrast by G-computation, with a subject bootstrap
(refit per replicate by default) and an identification-assumptions note.survmat prediction contract: an n x length(times) numeric matrix
carrying its grid in the "times" attribute ("t=<time>" column names kept
for display and the legacy metric helpers) and the predicted quantity in
"quantity". Missing predictions and non-increasing grids are rejected.default_times(): a recorded, data-dependent evaluation grid used whenever
times is omitted, so runs stay reproducible.cv() (with repeats), holdout(), group_cv(),
bootstrap(); reuse one spec across models for paired comparisons.fastgbm (CRAN): histogram gradient boosting, piecewise-exponential
objective by default so survival curves are available at arbitrary times.densemlp (CRAN): native-C++ MLP (no torch), IPCW-Brier discrete-time
loss by default, predictions interpolated onto the requested times.list_survlearners(); 22 learners total.fit_*(), predict_*(), tune_*(),
cv_survlearner(), score_survmodel(), benchmark*(),
summarise_benchmark(), estimate_rmst(), ...) remain exported and fully
supported. They are now marked internal in the manual and emit a one-time
per-session note. See ?\survalis-deprecated``. They are scheduled to
become unexported in a future release.compute_survcluster() and plot_survcluster(): unsupervised
clustering of predicted individualized survival curves via
unsurv::unsurv() (PAM on a weighted curve representation), registered
in list_interpretability_methods(). Added unsurv to Imports and
its paper's citation (El Badisy 2026, <doi:10.1093/bioadv/vbag218>)
to Description.screen_fdr(): univariate-Cox variable screening with
Benjamini-Hochberg FDR control, with a minscreen backfill guarantee.estimate_rmst() and plot_rmst(): standardized RMST
estimation via g-computation, with percentile bootstrap inference. Dispatch
between a marginal estimate and a two-arm causal-style contrast is by the
trt_col argument (NULL = marginal), matching plot_survmat()'s
existing group dispatch convention rather than separate function names.compute_shap_matrix() and plot_shap_beeswarm(): a beeswarm view
of SHAP contributions time-integrated over the full prediction horizon,
built on compute_shap()'s existing per-time Shapley decomposition.
compute_shap() gained an explicit features argument (defaulting to
setdiff(colnames(newdata), c(model$time, model$status))), replacing a
hardcoded c("time", "status", "event") exclusion, for consistency with
compute_interactions()'s existing features argument.roc_survmat() (full time-dependent ROC curve, IPCW-weighted like
auc_survmat()) and dca_survmat() (decision curve analysis / net benefit
for right-censored outcomes, using the same Ĝ(t) IPCW estimator as
brier() and auc_survmat()), each with plot()/plot_roc()/plot_dca()
methods.CoxBoost as a new survival learner: fit_coxboost(),
predict_coxboost(), and tune_coxboost(), wrapping the CoxBoost
package's likelihood-based componentwise boosting for the Cox partial
likelihood. Registered in list_survlearners() and usable directly
through benchmark().tune_glmnet()'s example in \donttest{} (per CRAN win-builder
pretest feedback: it exceeded the 5s/10s example runtime limit on
Debian/Windows).title argument to every plotting function (plot_ale(),
plot_pdp(), plot_shap(), plot_interactions(), plot_calibration(),
plot_counterfactual(), plot_surrogate(), plot_tree_surrogate(),
plot_varimp(), plot_survmat(), plot_survmetalearner_weights(),
plot_benchmark(), cv_plot(), plot_survcurve()). If omitted, the
previous automatically generated title is used (fully backward
compatible); pass title = NULL to omit the title entirely, for
journals that require caption-only figures.plot_shap()'s bar chart
had one): plot_ale() (both per_time and integrated), plot_shap()'s
time-dependent curve, plot_counterfactual(), plot_surrogate(), and
plot_varimp().plot_varimp() now draws a boxplot of the full per-repetition permutation
distribution for each feature instead of a single point estimate with no
uncertainty shown. compute_varimp() retains the per-repetition values
(previously discarded after computing summary stats) as a "raw_scores"
attribute on its return value, used by plot_varimp(); falls back to the
previous point-plot behavior for objects without that attribute (e.g.
hand-built summary tables).plot_interactions(type = "heatmap")'s viridis
scale so high interaction values are dark and low values are bright,
matching the conventional reading of heatmap intensity.plot_interactions(type = "heatmap"), which was genuinely hard to
read: the white -> steelblue gradient had too little contrast in the
mid-range, and the diagonal (self-interaction, value 0) blended into the
low end of the scale. Switched to scale_fill_viridis_c() (perceptually
uniform, high contrast), added an explicit na.value for any genuinely
missing cells, and fixed a squished legend by widening the colorbar guide.color/fill mapped to a variable) previously fell back to ggplot2's
default hue palette everywhere except plot_survcurve(); they now all use
scale_color_survalis()/scale_fill_survalis(). Single-series hardcoded
colors ("steelblue", "skyblue", "lightblue", "pink", "tomato",
plain "blue", and ad-hoc green/red hex codes for positive/negative
direction) now draw from the same shared Dark2-based palette instead of
arbitrary named/hex colors. This was explicitly deferred in PR #22 and is
now closed out.man/compute_tree_surrogate.Rd, man/plot_tree_surrogate.Rd,
and man/tune_survdnn.Rd were stale, hand-drifted copies using
\donttest{} (which runs under R CMD check --run-donttest, as CI does)
instead of the \dontrun{} already present in the roxygen source,
causing plot_tree_surrogate(tree_ranger, ...) to fail on an undefined
tree_ranger object. Regenerated all three from source via
devtools::document(); verified locally with
R CMD check --run-donttest (Status: OK), matching the CI configuration.summarise_benchmark() now rounds mean/sd/se/lower/upper to 3
decimals by default (digits = 3 argument), matching cv_summary()'s
convention; it previously returned full-precision values (e.g.
sd = 0.014142136).base_size to the shared theme_survalis() default (13)
everywhere: compute_shap.R, fit_survmetalearner.R's weights plot, and
plot_benchmark() previously carried over a hardcoded base_size = 14
from before the theme retrofit (PR #22).compute_shap(), compute_shap_mean(), compute_calibration(),
and plot_survmetalearner_weights() from dplyr/tidyr to data.table. This
was the remaining unqualified (non-dplyr::-prefixed) dplyr/tidyr usage
missed by the original file-by-file migration inventory.dplyr, tidyr, purrr, and tibble are now fully removed from
Imports: the package no longer depends on any tidyverse package for
its data-manipulation code; data.table is the sole engine throughout.benchmark_default_survlearners.R
(benchmark_default_survlearners(), .nested_surv_* helpers,
summarise_benchmark(), summarize_benchmark_results(),
best_survlearner()) from dplyr/tidyr/tibble to data.table. This
completes the file-by-file dplyr/tidyverse -> data.table migration across
the package. Reuses the shared .score_metrics() helper in
.nested_surv_score_predictions() instead of a fifth duplicated copy of
the per-metric scoring switch() block.cv_survmetalearner() from dplyr/tidyr/purrr/tibble to
data.table, reusing the shared .score_metrics() helper instead of a
third duplicated copy of the per-metric scoring switch() block.list_survlearners(), list_interpretability_methods(), and
list_metrics() from tibble::tibble() to data.table::data.table()
(cosmetic descriptive tables, no behavior change).plot_survmat() from dplyr/tidyr to data.table
(data.table::melt() for the wide-to-long reshape, [.data.table with
by = for the group/time summaries).compute_varimp() from dplyr/purrr/tibble to data.table.tune_survdnn() from dplyr/tidyr/purrr/tibble to data.table,
including the list-valued hidden architecture parameter (grid expansion
built manually over unique levels per parameter, since data.table::CJ()
doesn't support list-valued columns).tune_survsvm() from dplyr/tidyr/purrr/tibble to data.table
(grid expansion via data.table::CJ()); the CRAN-motivated refit-fallback
behavior (PR #14) is unchanged and still verified passing.tune_glmnet() from dplyr/tidyr/purrr/tibble to data.table,
including its tidyr::crossing() grid-expansion step (now
data.table::CJ(), a sorted-unique cross join with matching semantics).tune_selectcox() from dplyr/tidyr/purrr/tibble to data.table.tune_flexsurvreg() from dplyr/tidyr/purrr/tibble to data.table.
Added .map_rbind_dt() in R/dt-utils.R, a data.table replacement for
purrr::map_dfr() over a plain vector (as opposed to .pmap_rbind_dt()
for a parameter grid).tune_blackboost() from dplyr/tidyr/purrr/tibble to data.table.tune_bart() from dplyr/tidyr/purrr/tibble to data.table.tune_rsf() from dplyr/tidyr/purrr/tibble to data.table.tune_orsf() from dplyr/tidyr/purrr/tibble to data.table.tune_cforest() from dplyr/tidyr/purrr/tibble to data.table.tune_bnnsurv() from dplyr/tidyr/purrr/tibble to data.table.tune_xgboost() from dplyr/tidyr/purrr/tibble to data.table.tune_ranger() from dplyr/tidyr/purrr/tibble to data.table.benchmark_tuned_survlearners() silently dropping learners whose
tune_*() has been migrated to data.table: tuning_results[1, cols, drop = FALSE]
relies on data.frame [ semantics, but data.table's [ does not select
columns when cols is a variable (only a literal character vector
triggers that); it was returning the raw column-name vector instead of
a one-row parameter table, causing every fold to error and the learner
to be dropped with a warning. Added .select_cols() in R/dt-utils.R
that selects columns correctly for either a data.frame/tibble or a
data.table, so the nested-tuning code stays agnostic to migration state.theme_survalis()
instead of ad-hoc theme_minimal() calls with inconsistent base_size
values, so package figures share one consistent visual style: plot_ale(),
survmat plotting helpers, plot_surrogate()/plot_shap(), cv_plot(),
plot_pdp(), plot_interactions(), plot_counterfactual(),
plot_tree_surrogate(), plot_benchmark(), plot_varimp(),
fit_survmetalearner()'s plotting path. Hardcoded per-plot colors are
unchanged in this pass (follow-up).plot_survcurve(), a survminer-inspired Kaplan-Meier curve with
confidence ribbon, log-rank p-value annotation, and an aligned
number-at-risk table, built natively on theme_survalis() /
scale_color_survalis() (no dependency on the survminer package). The
risk table uses patchwork (added to Suggests).theme_survalis(), a shared ggplot2 theme, and
scale_color_survalis()/scale_fill_survalis(), colorblind-friendly
discrete scales (ColorBrewer "Dark2"-based, recycled/interpolated beyond
8 levels), for a consistent visual style across package figures. Not yet
applied to existing plotting functions (follow-up).tune_rpart() from dplyr/tidyr/purrr/tibble to data.table.
Added internal data.table helpers (R/dt-utils.R) shared by the ongoing
file-by-file migration of the remaining tune_*()/fit_*() grid-search
code (tracked in the project TODO).benchmark(), the single entry point for comparing survival
learners: tune = FALSE (default) dispatches to
benchmark_default_survlearners(), tune = TRUE dispatches to
benchmark_tuned_survlearners() (nested CV with per-learner tuning).
benchmark_default_survlearners() and benchmark_tuned_survlearners()
remain available directly.cv_survlearner(), cv_summary(),
score_survmodel()) from dplyr/tidyr/tibble/purrr to data.table; data.table
is now the main data-manipulation engine going forward, replacing the
dplyr/tidyverse approach used previously. This is a first step; the
remaining tuning/fitting code (tune_*()/fit_*()) still uses dplyr/purrr
and will be migrated incrementally.cv_summary() and score_survmodel()/cv_survlearner() metric values now
round to 3 decimals by default (digits = 3 argument on cv_summary()).data.table objects instead of tibbles
(is.data.frame() still holds; code relying on tibble-specific behavior
should call tibble::as_tibble() explicitly).timeroc_survmat(), a vectorized cumulative/dynamic time-dependent
AUC curve over a vector of evaluation times (Uno et al. 2007 / Heagerty
and Zheng 2005 estimator), matching timeROC::timeROC(weighting = "marginal")
to ~1e-3.auc_survmat() to define cases as events strictly before t_star
(time < t_star) rather than time <= t_star, matching the canonical
Uno/timeROC definition; this corrects the "auc" metric used throughout
score_survmodel(), benchmark_*(), and fit_survmetalearner().timeROC to Suggests for numerical validation in tests.plot_pdp() per-time facets using free y-axis scales, which made
survival probability panels visually incomparable across facets; now uses
a fixed [0, 1] scale via coord_cartesian().tune_survsvm(refit_best = TRUE) crashing when the top-ranked grid
candidate fails to refit on the full dataset (e.g., a quadprog QP
infeasibility that only manifests on certain BLAS backends, as seen on
CRAN's OpenBLAS check machine); it now falls back to the next-best
candidate and only errors if every candidate fails.\\dontrun{} wrappers with \\donttest{} for executable-but-longer workflows and kept fast examples unwrapped where feasible.devtools::document().run_dont_test = TRUE for CRAN resubmission readiness.plot_counterfactual() for visualizing counterfactual recommendations.plot_survmat() for plotting predicted survival curves, including grouped summaries.survdnn when the LibTorch runtime is missing.Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.