library(survival)
library(eventglm)
As of version 1.1.0, cumincglm
and rmeanglm
expect the argument model.censoring
to be a function. This function is the workhorse that does the computation of the pseudo observations that are later used in the generalized linear model. A number of computation methods are built in as “modules” in the file called “pseudo-modules.R”. Let us take a look at an example:
::pseudo_independent
eventglm#> function (formula, time, cause = 1, data, type = c("cuminc",
#> "survival", "rmean"), formula.censoring = NULL, ipcw.method = NULL)
#> {
#> margformula <- update.formula(formula, . ~ 1)
#> mr <- model.response(model.frame(margformula, data = data))
#> stopifnot(attr(mr, "type") %in% c("right", "mright"))
#> marginal.estimate <- survival::survfit(margformula, data = data)
#> if (type == "cuminc") {
#> POi <- get_pseudo_cuminc(marginal.estimate, time, cause,
#> mr)
#> }
#> else if (type == "survival") {
#> if (marginal.estimate$type != "right") {
#> stop("Survival estimand not available for outcome with censoring type",
#> marginal.estimate$type)
#> }
#> POi <- 1 - get_pseudo_cuminc(marginal.estimate, time,
#> cause, mr)
#> }
#> else if (type == "rmean") {
#> POi <- get_pseudo_rmean(marginal.estimate, time, cause,
#> mr)
#> }
#> POi
#> }
#> <bytecode: 0x0000000025aa9c80>
#> <environment: namespace:eventglm>
This function, and any pseudo observation module, must take the same named arguments (though they do not all have to be used), and return a vector of pseudo observations.
Let us see how to define a custom function for computation of pseudo observations. In this first example, we will fit a parametric survival model with survreg
marginally and do jackknife leave one out estimates. This may be useful if there is interval censoring, for example.
<- function(formula, time, cause = 1, data,
pseudo_parametric type = c("cuminc", "survival", "rmean"),
formula.censoring = NULL, ipcw.method = NULL){
<- update.formula(formula, . ~ 1)
margformula <- model.response(model.frame(margformula, data = data))
mr
<- survival::survreg(margformula, data = data,
marginal.estimate dist = "weibull")
<- pweibull(time, shape = 1 / marginal.estimate$scale,
theta scale = exp(marginal.estimate$coefficients[1]))
<- sapply(1:nrow(data), function(i) {
theta.i
<- survival::survreg(margformula, data = data[-i, ], dist = "weibull")
me pweibull(time, shape = 1 / me$scale,
scale = exp(me$coefficients[1]))
})
<- theta + (nrow(data) - 1) * (theta - theta.i)
POi
POi
}
Now let us try it out by passing it to the cumincglm
function and compare to the default independence estimator:
<- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
fitpara model.censoring = pseudo_parametric,
data = colon)
<- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
fitdef model.censoring = "independent",
data = colon)
::kable(sapply(list(parametric = fitpara, default = fitdef),
knitr coefficients))
parametric | default | |
---|---|---|
(Intercept) | 0.5473823 | 0.4891055 |
rxLev | -0.0216382 | -0.0292873 |
rxLev+5FU | -0.1488142 | -0.1326516 |
sex | 0.0008129 | -0.0102263 |
age | 0.0004233 | 0.0010047 |
You can also refer to the function with a string, omitting the “pseudo_” prefix, if you wish, e.g.,
<- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
fit1 model.censoring = "parametric",
data = colon)
When the survival package version 3.0 was released, it became possible to get the influence function values returned from some estimation functions. These efficient influence functions are used in the variance calculations, and they are related to pseudo observations. More information is available in the “pseudo.Rnw” vignette of the development version of survival. We can use this feature to create a custom function for infinitesimal jackknife pseudo observations:
<- function(formula, time, cause = 1, data,
pseudo_infjack type = c("cuminc", "survival", "rmean"),
formula.censoring = NULL, ipcw.method = NULL) {
<- survival::survfit(update.formula(formula, . ~ 1),
marginal.estimate2 data = data, influence = TRUE)
<- sapply(time, function(x) max(which(marginal.estimate2$time <= x)))
tdex
<- marginal.estimate2$surv[tdex]
pstate
## S(t) + (n)[S(t) -S_{-i}(t)]
<- matrix(pstate, nrow = marginal.estimate2$n, ncol = length(time), byrow = TRUE) +
POi $n) *
(marginal.estimate2$influence.surv[, tdex + 1])
(marginal.estimate2
POi
}
Note that this computes pseudo observations for survival, rather than the cumulative incidence, so to compare we can use the survival = TRUE option. Now we try it out
<- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
fitinf model.censoring = "infjack",
data = colon)
<- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
fitdefsurv survival = TRUE,
data = colon)
::kable(sapply(list(infjack = fitinf, default = fitdefsurv),
knitr coefficients))
infjack | default | |
---|---|---|
(Intercept) | 0.5108264 | 0.5108945 |
rxLev | 0.0292609 | 0.0292873 |
rxLev+5FU | 0.1326361 | 0.1326516 |
sex | 0.0102568 | 0.0102263 |
age | -0.0010036 | -0.0010047 |
This opens up a lot of possibilities for future extensions of eventglm
, and will also make it easier to maintain. Try it out with different methods, and let us know what methods you are using or would like to use.