Learning objectives
In this lesson you will
- Learn how to extend
eventglm
to compute pseudo observations in a new way
Setup
Library the survival
package and then the eventglm
package. We will use some commands from survival
to make sense of what is going on in the regression models.
library(survival)
library(eventglm)
Pseudo observation computation modules
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:
eventglm::pseudo_independent
## 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: 0x00000000204d3180>
## <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.
Custom computation functions
Exercise
Example: Parametric pseudo observations
Write a function that fits a parametric survival model with survreg
marginally and do jackknife leave one out estimates to construct pseudo-observations. This may be useful if there is interval censoring, for example.
Solution
pseudo_parametric <- 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))
marginal.estimate <- survival::survreg(margformula, data = data,
dist = "weibull")
theta <- pweibull(time, shape = 1 / marginal.estimate$scale,
scale = exp(marginal.estimate$coefficients[1]))
theta.i <- sapply(1:nrow(data), function(i) {
me <- survival::survreg(margformula, data = data[-i, ], dist = "weibull")
pweibull(time, shape = 1 / me$scale,
scale = exp(me$coefficients[1]))
})
POi <- theta + (nrow(data) - 1) * (theta - theta.i)
POi
}
Now let us try it out by passing it to the cumincglm
function and compare to the default independence estimator:
fitpara <- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
model.censoring = pseudo_parametric,
data = colon)
fitdef <- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
model.censoring = "independent",
data = colon)
knitr::kable(sapply(list(parametric = fitpara, default = fitdef),
coefficients))
(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.,
fit1 <- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
model.censoring = "parametric",
data = colon)
Example 2: infinitesimal jackknife
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. This feature has been incorporated into the latest version of eventglm
, available in the pseudo_infjack
module.
Below here is a simplified version. Use this as inspiration to create a module for an estimand of interest in a multi-state model (say the illness death model).
pseudo_infjack <- function(formula, time, cause = 1, data,
type = c("cuminc", "survival", "rmean"),
formula.censoring = NULL, ipcw.method = NULL) {
marginal.estimate2 <- survival::survfit(update.formula(formula, . ~ 1),
data = data, influence = TRUE)
tdex <- sapply(time, function(x) max(which(marginal.estimate2$time <= x)))
pstate <- marginal.estimate2$surv[tdex]
## S(t) + (n)[S(t) -S_{-i}(t)]
POi <- matrix(pstate, nrow = marginal.estimate2$n, ncol = length(time), byrow = TRUE) +
(marginal.estimate2$n) *
(marginal.estimate2$influence.surv[, tdex])
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
fitinf <- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
model.censoring = "infjack",
survival = TRUE,
data = colon)
fitdefsurv <- cumincglm(Surv(time, status) ~ rx + sex + age, time = 2500,
survival = TRUE,
data = colon)
knitr::kable(sapply(list(infjack = fitinf, default = fitdefsurv),
coefficients))
(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 |
LS0tDQp0aXRsZTogIkN1c3RvbSBwc2V1ZG8gb2JzZXJ2YXRpb24gbW9kdWxlcyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCmJpYmxpb2dyYXBoeTogcmVmcy5iaWINCi0tLQ0KDQojIyMgTGVhcm5pbmcgb2JqZWN0aXZlcyB7LmFsZXJ0IC5hbGVydC1zdWNjZXNzfQ0KDQpJbiB0aGlzIGxlc3NvbiB5b3Ugd2lsbCANCg0KMS4gTGVhcm4gaG93IHRvIGV4dGVuZCBgZXZlbnRnbG1gIHRvIGNvbXB1dGUgcHNldWRvIG9ic2VydmF0aW9ucyBpbiBhIG5ldyB3YXkNCg0KDQojIyBTZXR1cA0KDQpMaWJyYXJ5IHRoZSBgc3Vydml2YWxgIHBhY2thZ2UgYW5kIHRoZW4gdGhlIGBldmVudGdsbWAgcGFja2FnZS4gV2Ugd2lsbCB1c2Ugc29tZSBjb21tYW5kcyBmcm9tIGBzdXJ2aXZhbGAgdG8gbWFrZSBzZW5zZSBvZiB3aGF0IGlzIGdvaW5nIG9uIGluIHRoZSByZWdyZXNzaW9uIG1vZGVscy4NCg0KDQpgYGB7cn0NCmxpYnJhcnkoc3Vydml2YWwpDQpsaWJyYXJ5KGV2ZW50Z2xtKQ0KYGBgDQoNCg0KIyMgUHNldWRvIG9ic2VydmF0aW9uIGNvbXB1dGF0aW9uIG1vZHVsZXMNCg0KQXMgb2YgdmVyc2lvbiAxLjEuMCwgYGN1bWluY2dsbWAgYW5kIGBybWVhbmdsbWAgZXhwZWN0IHRoZSBhcmd1bWVudCBgbW9kZWwuY2Vuc29yaW5nYCB0byBiZSBhIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIGlzIHRoZSB3b3JraG9yc2UgdGhhdCBkb2VzIHRoZSBjb21wdXRhdGlvbiBvZiB0aGUgcHNldWRvIG9ic2VydmF0aW9ucyB0aGF0IGFyZSBsYXRlciB1c2VkIGluIHRoZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWwuIEEgbnVtYmVyIG9mIGNvbXB1dGF0aW9uIG1ldGhvZHMgYXJlIGJ1aWx0IGluIGFzICJtb2R1bGVzIiBpbiB0aGUgZmlsZSBjYWxsZWQgInBzZXVkby1tb2R1bGVzLlIiLiBMZXQgdXMgdGFrZSBhIGxvb2sgYXQgYW4gZXhhbXBsZTogDQoNCmBgYHtyfQ0KZXZlbnRnbG06OnBzZXVkb19pbmRlcGVuZGVudA0KYGBgDQoNClRoaXMgZnVuY3Rpb24sIGFuZCBhbnkgcHNldWRvIG9ic2VydmF0aW9uIG1vZHVsZSwgbXVzdCB0YWtlIHRoZSBzYW1lIG5hbWVkIGFyZ3VtZW50cyAodGhvdWdoIHRoZXkgZG8gbm90IGFsbCBoYXZlIHRvIGJlIHVzZWQpLCBhbmQgcmV0dXJuIGEgdmVjdG9yIG9mIHBzZXVkbyBvYnNlcnZhdGlvbnMuIA0KDQoNCiMjIEN1c3RvbSBjb21wdXRhdGlvbiBmdW5jdGlvbnMNCg0KIyMjIEV4ZXJjaXNlIHsuYWxlcnQgLmFsZXJ0LXdhcm5pbmd9DQoNCg0KIyMjIyBFeGFtcGxlOiBQYXJhbWV0cmljIHBzZXVkbyBvYnNlcnZhdGlvbnMNCg0KV3JpdGUgYSBmdW5jdGlvbiB0aGF0IGZpdHMgYSBwYXJhbWV0cmljIHN1cnZpdmFsIG1vZGVsIHdpdGggYHN1cnZyZWdgIG1hcmdpbmFsbHkgYW5kIGRvIGphY2trbmlmZSBsZWF2ZSBvbmUgb3V0IGVzdGltYXRlcyB0byBjb25zdHJ1Y3QgcHNldWRvLW9ic2VydmF0aW9ucy4gVGhpcyBtYXkgYmUgdXNlZnVsIGlmIHRoZXJlIGlzIGludGVydmFsIGNlbnNvcmluZywgZm9yIGV4YW1wbGUuIA0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxzdHJvbmc+U29sdXRpb248L3N0cm9uZz48L3N1bW1hcnk+DQoNCmBgYHtyfQ0KcHNldWRvX3BhcmFtZXRyaWMgPC0gZnVuY3Rpb24oZm9ybXVsYSwgdGltZSwgY2F1c2UgPSAxLCBkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IGMoImN1bWluYyIsICJzdXJ2aXZhbCIsICJybWVhbiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgZm9ybXVsYS5jZW5zb3JpbmcgPSBOVUxMLCBpcGN3Lm1ldGhvZCA9IE5VTEwpew0KICBtYXJnZm9ybXVsYSA8LSB1cGRhdGUuZm9ybXVsYShmb3JtdWxhLCAuIH4gMSkNCiAgbXIgPC0gbW9kZWwucmVzcG9uc2UobW9kZWwuZnJhbWUobWFyZ2Zvcm11bGEsIGRhdGEgPSBkYXRhKSkNCiAgDQogIG1hcmdpbmFsLmVzdGltYXRlIDwtIHN1cnZpdmFsOjpzdXJ2cmVnKG1hcmdmb3JtdWxhLCBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgPSAid2VpYnVsbCIpDQogIHRoZXRhIDwtIHB3ZWlidWxsKHRpbWUsIHNoYXBlID0gMSAvIG1hcmdpbmFsLmVzdGltYXRlJHNjYWxlLCANCiAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBleHAobWFyZ2luYWwuZXN0aW1hdGUkY29lZmZpY2llbnRzWzFdKSkNCiAgDQogIHRoZXRhLmkgPC0gc2FwcGx5KDE6bnJvdyhkYXRhKSwgZnVuY3Rpb24oaSkgew0KICAgIA0KICAgIG1lIDwtIHN1cnZpdmFsOjpzdXJ2cmVnKG1hcmdmb3JtdWxhLCBkYXRhID0gZGF0YVstaSwgXSwgZGlzdCA9ICJ3ZWlidWxsIikNCiAgICBwd2VpYnVsbCh0aW1lLCBzaGFwZSA9IDEgLyBtZSRzY2FsZSwgDQogICAgICAgICAgICAgICAgICAgIHNjYWxlID0gZXhwKG1lJGNvZWZmaWNpZW50c1sxXSkpDQogIA0KICAgIA0KICB9KQ0KICANCiAgUE9pIDwtIHRoZXRhICArIChucm93KGRhdGEpIC0gMSkgKiAodGhldGEgLSB0aGV0YS5pKQ0KICBQT2kNCn0NCmBgYA0KDQoNCk5vdyBsZXQgdXMgdHJ5IGl0IG91dCBieSBwYXNzaW5nIGl0IHRvIHRoZSBgY3VtaW5jZ2xtYCBmdW5jdGlvbiBhbmQgY29tcGFyZSB0byB0aGUgZGVmYXVsdCBpbmRlcGVuZGVuY2UgZXN0aW1hdG9yOiANCg0KYGBge3J9DQpmaXRwYXJhIDwtIGN1bWluY2dsbShTdXJ2KHRpbWUsIHN0YXR1cykgfiByeCArIHNleCArIGFnZSwgdGltZSA9IDI1MDAsIA0KICAgICAgICAgICAgICAgICAgbW9kZWwuY2Vuc29yaW5nID0gcHNldWRvX3BhcmFtZXRyaWMsIA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KZml0ZGVmIDwtIGN1bWluY2dsbShTdXJ2KHRpbWUsIHN0YXR1cykgfiByeCArIHNleCArIGFnZSwgdGltZSA9IDI1MDAsIA0KICAgICAgICAgICAgICAgICAgbW9kZWwuY2Vuc29yaW5nID0gImluZGVwZW5kZW50IiwgDQogICAgICAgICAgICAgICAgICBkYXRhID0gY29sb24pDQprbml0cjo6a2FibGUoc2FwcGx5KGxpc3QocGFyYW1ldHJpYyA9IGZpdHBhcmEsIGRlZmF1bHQgPSBmaXRkZWYpLCANCiAgICAgICBjb2VmZmljaWVudHMpKQ0KYGBgDQoNCllvdSBjYW4gYWxzbyByZWZlciB0byB0aGUgZnVuY3Rpb24gd2l0aCBhIHN0cmluZywgb21pdHRpbmcgdGhlICJwc2V1ZG9fIiBwcmVmaXgsIGlmIHlvdSB3aXNoLCBlLmcuLCANCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCmZpdDEgPC0gY3VtaW5jZ2xtKFN1cnYodGltZSwgc3RhdHVzKSB+IHJ4ICsgc2V4ICsgYWdlLCB0aW1lID0gMjUwMCwgDQogICAgICAgICAgICAgICAgICBtb2RlbC5jZW5zb3JpbmcgPSAicGFyYW1ldHJpYyIsIA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KYGBgDQoNCg0KPC9kZXRhaWxzPg0KDQoNCiMjIyBFeGFtcGxlIDI6IGluZmluaXRlc2ltYWwgamFja2tuaWZlDQoNCldoZW4gdGhlIHN1cnZpdmFsIHBhY2thZ2UgdmVyc2lvbiAzLjAgd2FzIHJlbGVhc2VkLCBpdCBiZWNhbWUgcG9zc2libGUgdG8gZ2V0IHRoZSBpbmZsdWVuY2UgZnVuY3Rpb24gdmFsdWVzIHJldHVybmVkIGZyb20gc29tZSBlc3RpbWF0aW9uIGZ1bmN0aW9ucy4gVGhlc2UgZWZmaWNpZW50IGluZmx1ZW5jZSBmdW5jdGlvbnMgYXJlIHVzZWQgaW4gdGhlIHZhcmlhbmNlIGNhbGN1bGF0aW9ucywgYW5kIHRoZXkgYXJlIHJlbGF0ZWQgdG8gcHNldWRvIG9ic2VydmF0aW9ucy4gTW9yZSBpbmZvcm1hdGlvbiBpcyBhdmFpbGFibGUgaW4gdGhlICJwc2V1ZG8uUm53IiB2aWduZXR0ZSBvZiB0aGUgZGV2ZWxvcG1lbnQgdmVyc2lvbiBvZiBzdXJ2aXZhbC4gVGhpcyBmZWF0dXJlIGhhcyBiZWVuIGluY29ycG9yYXRlZCBpbnRvIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBgZXZlbnRnbG1gLCBhdmFpbGFibGUgaW4gdGhlIGBwc2V1ZG9faW5mamFja2AgbW9kdWxlLiANCg0KDQpCZWxvdyBoZXJlIGlzIGEgc2ltcGxpZmllZCB2ZXJzaW9uLiBVc2UgdGhpcyBhcyBpbnNwaXJhdGlvbiB0byBjcmVhdGUgYSBtb2R1bGUgZm9yIGFuIGVzdGltYW5kIG9mIGludGVyZXN0IGluIGEgbXVsdGktc3RhdGUgbW9kZWwgKHNheSB0aGUgaWxsbmVzcyBkZWF0aCBtb2RlbCkuIA0KDQpgYGB7cn0NCnBzZXVkb19pbmZqYWNrIDwtIGZ1bmN0aW9uKGZvcm11bGEsIHRpbWUsIGNhdXNlID0gMSwgZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBjKCJjdW1pbmMiLCAic3Vydml2YWwiLCAicm1lYW4iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm11bGEuY2Vuc29yaW5nID0gTlVMTCwgaXBjdy5tZXRob2QgPSBOVUxMKSB7DQogIA0KICBtYXJnaW5hbC5lc3RpbWF0ZTIgPC0gc3Vydml2YWw6OnN1cnZmaXQodXBkYXRlLmZvcm11bGEoZm9ybXVsYSwgLiB+IDEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIGluZmx1ZW5jZSA9IFRSVUUpDQogICAgIHRkZXggPC0gc2FwcGx5KHRpbWUsIGZ1bmN0aW9uKHgpIG1heCh3aGljaChtYXJnaW5hbC5lc3RpbWF0ZTIkdGltZSA8PSB4KSkpDQogICAgIHBzdGF0ZSA8LSBtYXJnaW5hbC5lc3RpbWF0ZTIkc3Vydlt0ZGV4XQ0KICAgICAjIyBTKHQpICsgKG4pW1ModCkgLVNfey1pfSh0KV0NCiAgICAgUE9pIDwtIG1hdHJpeChwc3RhdGUsIG5yb3cgPSBtYXJnaW5hbC5lc3RpbWF0ZTIkbiwgbmNvbCA9IGxlbmd0aCh0aW1lKSwgYnlyb3cgPSBUUlVFKSArDQogICAgICAgICAobWFyZ2luYWwuZXN0aW1hdGUyJG4pICoNCiAgICAgICAgIChtYXJnaW5hbC5lc3RpbWF0ZTIkaW5mbHVlbmNlLnN1cnZbLCB0ZGV4XSkNCiAgICAgDQogICAgIFBPaQ0KfQ0KYGBgDQoNCk5vdGUgdGhhdCB0aGlzIGNvbXB1dGVzIHBzZXVkbyBvYnNlcnZhdGlvbnMgZm9yIHN1cnZpdmFsLCByYXRoZXIgdGhhbiB0aGUgY3VtdWxhdGl2ZSBpbmNpZGVuY2UsIHNvIHRvIGNvbXBhcmUgd2UgY2FuIHVzZSB0aGUgc3Vydml2YWwgPSBUUlVFIG9wdGlvbi4gTm93IHdlIHRyeSBpdCBvdXQNCg0KYGBge3J9DQpmaXRpbmYgPC0gY3VtaW5jZ2xtKFN1cnYodGltZSwgc3RhdHVzKSB+IHJ4ICsgc2V4ICsgYWdlLCB0aW1lID0gMjUwMCwgDQogICAgICAgICAgICAgICAgICBtb2RlbC5jZW5zb3JpbmcgPSAiaW5mamFjayIsIA0KICAgICAgICAgICAgICAgICAgc3Vydml2YWwgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KZml0ZGVmc3VydiA8LSBjdW1pbmNnbG0oU3Vydih0aW1lLCBzdGF0dXMpIH4gcnggKyBzZXggKyBhZ2UsIHRpbWUgPSAyNTAwLCANCiAgICAgICAgICAgICAgICAgIHN1cnZpdmFsID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb2xvbikNCmtuaXRyOjprYWJsZShzYXBwbHkobGlzdChpbmZqYWNrID0gZml0aW5mLCBkZWZhdWx0ID0gZml0ZGVmc3VydiksIA0KICAgICAgIGNvZWZmaWNpZW50cykpDQpgYGANCg==