Skip to contents

Run forward, backward, or two-way stepwise selection on an existing hazard fit using Wald p-values or AIC deltas as the entry / retention criterion. Phase-specific entry is supported for multiphase models: a covariate can enter one phase and not another.

Usage

hzr_stepwise(
  fit,
  scope = NULL,
  data,
  direction = c("both", "forward", "backward"),
  criterion = c("wald", "aic"),
  slentry = 0.3,
  slstay = 0.2,
  max_steps = 50L,
  max_move = 4L,
  force_in = character(),
  force_out = character(),
  trace = TRUE,
  ...
)

# S3 method for class 'hzr_stepwise'
print(x, ...)

# S3 method for class 'hzr_stepwise'
summary(object, ...)

# S3 method for class 'summary.hzr_stepwise'
print(x, ...)

# S3 method for class 'hzr_stepwise'
as.data.frame(x, ...)

Arguments

fit

A fitted hazard object built via the formula = Surv(...) ~ predictors, data = df interface.

scope

Candidate set. NULL (default) uses every data-frame column not already in the model for every phase. For single-distribution fits, pass a one-sided formula (~ age + nyha) or a character vector of names. For multiphase fits, pass a named list of one-sided formulas keyed by phase.

data

Data frame the base fit was built on. Required for refits.

direction

Search strategy — one of "both" (default), "forward", or "backward". Controls whether variables may only enter, only leave, or both. See the Selection direction and criterion section.

criterion

Entry / retention rule — one of "wald" (default) or "aic". "wald" applies SAS-style p-value thresholds (slentry / slstay); "aic" adds or drops whenever it lowers the AIC. See the Selection direction and criterion section.

slentry

Entry p-value threshold for the Wald criterion. Default 0.30 matches SAS SLENTRY.

slstay

Retention p-value threshold for the Wald criterion. Default 0.20 matches SAS SLSTAY.

max_steps

Hard cap on total accepted actions. Emits a warning() if hit. Default 50.

max_move

Per-variable oscillation cap. When a variable has entered + exited more than max_move times it is frozen for the remainder of the run. Default 4.

force_in

Character vector of variables that must remain in the model. Such variables are still scored and reported in the selection trace, but are never dropped.

force_out

Character vector of variables that may never be considered as candidates.

trace

Logical; print step-by-step progress to the console. Default TRUE.

...

Unused.

x

An hzr_stepwise object.

object

An hzr_stepwise object.

Value

An object of class c("hzr_stepwise", "hazard") – the final fit augmented with:

steps

Data frame with one row per accepted / frozen action; see Details.

scope

Record of the candidate scope, plus force_in, force_out, and the frozen set.

criteria

Named list of the threshold / direction settings actually applied.

trace_msg

Character vector of the trace lines, captured regardless of the trace flag.

elapsed

difftime from start to finish.

final_call

The call that produced this result.

print.hzr_stepwise returns x invisibly.

summary.hzr_stepwise returns a summary.hzr_stepwise object (extends summary.hazard) with $stepwise_steps and $stepwise_trace appended.

print.summary.hzr_stepwise returns x invisibly.

as.data.frame.hzr_stepwise returns the $steps data frame.

Details

The steps data frame has columns:

step_num

Integer sequence starting at 1.

action

"enter", "drop", or "frozen".

variable

Variable affected.

phase

Phase name (multiphase) or NA_character_.

criterion

"wald" or "aic".

score

Winning score used for the decision.

stat, df

Wald statistic and degrees of freedom.

p_value, delta_aic

Always populated when computable, regardless of the active criterion.

logLik, aic, n_coef

Goodness-of-fit diagnostics of the model after this step.

Selection direction and criterion

Two arguments shape the search. direction decides which moves are allowed at each step; criterion decides how a candidate move is scored and whether it is accepted.

direction = "forward"

Start from the base model and only add variables — the best eligible candidate enters each step until none clears the entry rule. Variables never leave once in.

direction = "backward"

Start from the full candidate model and only drop variables — the weakest term leaves each step until all survivors clear the retention rule.

direction = "both" (default)

Two-way stepwise: after each entry, already-selected variables are re-tested and may be dropped. This is the SAS SELECTION = STEPWISE strategy. max_move caps how often a single variable may oscillate before it is frozen.

criterion = "wald" (default)

Accept moves on SAS-style significance thresholds, using the Wald \(\chi^2\) of the affected coefficient(s): a candidate enters if its p-value is below slentry, and a term is dropped if its p-value rises above slstay. Entry candidates are scored from a refit that adds the candidate (so its new coefficient can be tested); drop candidates are scored from the current model's Wald p-values without a per-candidate refit, and a single refit is run only after a drop is chosen. Note this differs algorithmically from C/SAS HAZARD, which selects on a score (Q) statistic evaluated without refitting; the two can take different step paths even when they converge to a similar final model.

criterion = "aic"

Accept any move with \(\Delta\mathrm{AIC} < 0\) (a strictly better penalised fit), ignoring slentry / slstay. Entry candidates use the actual \(\Delta\mathrm{AIC}\) from the candidate refit; drop candidates use a Wald-to-likelihood-ratio approximation, \(\Delta\mathrm{AIC} \approx W - 2\,\mathrm{df}\), computed from the current model without a per-candidate refit (the chosen drop is refit afterwards). Use this for a non-significance-based, information-criterion search.

See also

hazard() for the base model and hzr_phase() for multiphase scopes; stepwise_trace() to retrieve the captured selection log.

Examples

data(avc)
avc <- na.omit(avc)
base <- hazard(survival::Surv(int_dead, dead) ~ age,
               data = avc, dist = "weibull", fit = TRUE)
# \donttest{
sw <- hzr_stepwise(base, scope = ~ age + nyha,
                   data = avc, direction = "forward",
                   control = list(n_starts = 1))
#> Stepwise selection (direction = forward, criterion = wald, slentry = 0.30, slstay = 0.20)
#> 
#> Warning: Stepwise forward: candidate refit failed for nyha.
#> (no further action after 0 steps)
#> 
#> Final model: 0 covariates, logLik = NA, AIC = NA
print(sw)
#> Stepwise selection (direction = forward, criterion = wald, slentry = 0.30, slstay = 0.20)
#> 
#> (no further action after 0 steps)
#> 
#> Final model: 0 covariates, logLik = NA, AIC = NA
# }