Perform K-fold cross-validation to select the kernel bandwidth for skmle().
Usage
skmle_cv(
formula,
data,
id,
obs_times,
s = 0,
K = 5,
h_grid = NULL,
n_h = 10,
nknots = 3,
lq_nodes = 64,
maxeval = 10000,
xtol_rel = 1e-06,
seed = NULL,
quiet = FALSE,
one_sided = TRUE
)
# S3 method for class 'cv.skmle'
print(x, ...)Arguments
- formula
A model formula. The left-hand side must be a
survival::Surv()response and the right-hand side must contain at least one covariate.- data
Data frame containing the variables used in
formula,id, andobs_times.- id
Subject identifier. Non-numeric identifiers are allowed and are internally converted to integer subject codes.
- obs_times
Longitudinal observation times aligned row-wise with
data. Times may be on any scale; the sieve basis and the cumulative-hazard quadrature are built on the observed follow-up, so there is no need to rescale to the unit interval first.hmust be on the same scale.- s
Box-Cox transformation parameter, defaulting to
0.s = 0is the proportional hazards model,s = 1is the additive hazards model, and values in between interpolate. If you do not have a reason to choose otherwise, the default is the familiar Cox model.- K
Number of folds.
- h_grid
Optional numeric vector of candidate bandwidth values. If
NULL, a grid is generated automatically from the observed time gaps.- n_h
Number of candidate bandwidths to generate when
h_gridisNULL.- nknots
Number of interior knots used in the sieve approximation of the baseline component. Knots are placed at
(1:nknots)/(nknots + 1). The basis is a natural cubic spline (splines::ns); its order is fixed, which is why there is nonorderargument.- lq_nodes
Number of Legendre-Gauss quadrature nodes used in numerical integration.
- maxeval
Maximum number of optimizer evaluations.
- xtol_rel
Relative convergence tolerance passed to the optimizer.
- seed
Optional integer seed for the random subject-to-fold assignment. If
NULL, the current RNG state is used and no explicit seed is set.- quiet
Logical; if
TRUE, suppress progress output.- one_sided
Logical.
TRUE(the default) uses a half kernel: only covariate observations strictly before the event or quadrature time inform that time, which is the risk-set restriction and the estimator as published.FALSEuses a full, two-sided kernel, smoothing the covariate path from both sides. The switch applies to the risk-set averages inside the C++ backend as well as to the row weights, so the two are always consistent.- x
A
cv.skmleobject.- ...
Ignored.
Value
An object of class cv.skmle with components:
h_cv: selected bandwidth,fit:skmlefit refit on the full data,cv_results: data frame of candidate bandwidths and CV losses,h_grid: bandwidth grid used in the search,fold_id: the subject-to-fold assignment vector (lengthn),seed: the value ofseedsupplied by the user, orNULL,call: the matched call.
Details
skmle_cv() splits subjects across folds. Several rows belong to the same
subject in long format, so splitting by row would put one subject on both
sides of the split.
After choosing the bandwidth with the smallest average validation loss, the
function refits skmle() on the full data set using the selected value.
Because the fold assignment is random, pass seed (or set.seed() before
calling) to make the grid selection reproducible.
Kernel choice
one_sided is used inside the fold loop as well as being passed through to
the refit, so the bandwidth is selected under the same kernel the final fit
uses.
Examples
# \donttest{
library(survival)
set.seed(123)
dat <- sim_skmle_data(
n = 60,
mu = function(tt) 8 * (0.75 + (0.5 - tt)^2),
mu_bar = 8,
alpha = function(tt) 0.5 * 0.75 + 0.75 * (tt * (1 - sin(2 * pi * (tt - 0.25)))),
beta = c(1, -0.5),
s = 0,
cen = 0.7
)
cv_fit <- skmle_cv(
Surv(X, delta) ~ covariates,
data = dat,
id = id,
obs_times = obs_times,
s = 0,
K = 3,
h_grid = c(0.3, 0.4, 0.5),
seed = 2026,
quiet = TRUE
)
cv_fit$h_cv
#> [1] 0.3
cv_fit$cv_results
#> # A tibble: 3 × 2
#> h cvloss
#> <dbl> <dbl>
#> 1 0.3 0.475
#> 2 0.4 0.517
#> 3 0.5 0.530
summary(cv_fit$fit)
#> Call:
#> skmle::skmle(formula = Surv(X, delta) ~ covariates, data = dat,
#> id = id, obs_times = obs_times, s = 0, h = 0.3)
#>
#> n= 60
#>
#> Estimate Std. Error z value Pr(>|z|)
#> covariates1 1.15277 0.48689 2.3676 0.0179 *
#> covariates2 -0.23009 0.36932 -0.6230 0.5333
#> ---
#> Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#>
#> Log-likelihood: 0.213
# }