Learning objectives

In this lesson you will

  1. 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))
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.,

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))
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
LS0tDQp0aXRsZTogIkN1c3RvbSBwc2V1ZG8gb2JzZXJ2YXRpb24gbW9kdWxlcyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cNCmJpYmxpb2dyYXBoeTogcmVmcy5iaWINCi0tLQ0KDQojIyMgTGVhcm5pbmcgb2JqZWN0aXZlcyB7LmFsZXJ0IC5hbGVydC1zdWNjZXNzfQ0KDQpJbiB0aGlzIGxlc3NvbiB5b3Ugd2lsbCANCg0KMS4gTGVhcm4gaG93IHRvIGV4dGVuZCBgZXZlbnRnbG1gIHRvIGNvbXB1dGUgcHNldWRvIG9ic2VydmF0aW9ucyBpbiBhIG5ldyB3YXkNCg0KDQojIyBTZXR1cA0KDQpMaWJyYXJ5IHRoZSBgc3Vydml2YWxgIHBhY2thZ2UgYW5kIHRoZW4gdGhlIGBldmVudGdsbWAgcGFja2FnZS4gV2Ugd2lsbCB1c2Ugc29tZSBjb21tYW5kcyBmcm9tIGBzdXJ2aXZhbGAgdG8gbWFrZSBzZW5zZSBvZiB3aGF0IGlzIGdvaW5nIG9uIGluIHRoZSByZWdyZXNzaW9uIG1vZGVscy4NCg0KDQpgYGB7cn0NCmxpYnJhcnkoc3Vydml2YWwpDQpsaWJyYXJ5KGV2ZW50Z2xtKQ0KYGBgDQoNCg0KIyMgUHNldWRvIG9ic2VydmF0aW9uIGNvbXB1dGF0aW9uIG1vZHVsZXMNCg0KQXMgb2YgdmVyc2lvbiAxLjEuMCwgYGN1bWluY2dsbWAgYW5kIGBybWVhbmdsbWAgZXhwZWN0IHRoZSBhcmd1bWVudCBgbW9kZWwuY2Vuc29yaW5nYCB0byBiZSBhIGZ1bmN0aW9uLiBUaGlzIGZ1bmN0aW9uIGlzIHRoZSB3b3JraG9yc2UgdGhhdCBkb2VzIHRoZSBjb21wdXRhdGlvbiBvZiB0aGUgcHNldWRvIG9ic2VydmF0aW9ucyB0aGF0IGFyZSBsYXRlciB1c2VkIGluIHRoZSBnZW5lcmFsaXplZCBsaW5lYXIgbW9kZWwuIEEgbnVtYmVyIG9mIGNvbXB1dGF0aW9uIG1ldGhvZHMgYXJlIGJ1aWx0IGluIGFzICJtb2R1bGVzIiBpbiB0aGUgZmlsZSBjYWxsZWQgInBzZXVkby1tb2R1bGVzLlIiLiBMZXQgdXMgdGFrZSBhIGxvb2sgYXQgYW4gZXhhbXBsZTogDQoNCmBgYHtyfQ0KZXZlbnRnbG06OnBzZXVkb19pbmRlcGVuZGVudA0KYGBgDQoNClRoaXMgZnVuY3Rpb24sIGFuZCBhbnkgcHNldWRvIG9ic2VydmF0aW9uIG1vZHVsZSwgbXVzdCB0YWtlIHRoZSBzYW1lIG5hbWVkIGFyZ3VtZW50cyAodGhvdWdoIHRoZXkgZG8gbm90IGFsbCBoYXZlIHRvIGJlIHVzZWQpLCBhbmQgcmV0dXJuIGEgdmVjdG9yIG9mIHBzZXVkbyBvYnNlcnZhdGlvbnMuIA0KDQoNCiMjIEN1c3RvbSBjb21wdXRhdGlvbiBmdW5jdGlvbnMNCg0KIyMjIEV4ZXJjaXNlIHsuYWxlcnQgLmFsZXJ0LXdhcm5pbmd9DQoNCg0KIyMjIyBFeGFtcGxlOiBQYXJhbWV0cmljIHBzZXVkbyBvYnNlcnZhdGlvbnMNCg0KV3JpdGUgYSBmdW5jdGlvbiB0aGF0IGZpdHMgYSBwYXJhbWV0cmljIHN1cnZpdmFsIG1vZGVsIHdpdGggYHN1cnZyZWdgIG1hcmdpbmFsbHkgYW5kIGRvIGphY2trbmlmZSBsZWF2ZSBvbmUgb3V0IGVzdGltYXRlcyB0byBjb25zdHJ1Y3QgcHNldWRvLW9ic2VydmF0aW9ucy4gVGhpcyBtYXkgYmUgdXNlZnVsIGlmIHRoZXJlIGlzIGludGVydmFsIGNlbnNvcmluZywgZm9yIGV4YW1wbGUuIA0KDQo8ZGV0YWlscz4NCjxzdW1tYXJ5PjxzdHJvbmc+U29sdXRpb248L3N0cm9uZz48L3N1bW1hcnk+DQoNCmBgYHtyfQ0KcHNldWRvX3BhcmFtZXRyaWMgPC0gZnVuY3Rpb24oZm9ybXVsYSwgdGltZSwgY2F1c2UgPSAxLCBkYXRhLA0KICAgICAgICAgICAgICAgICAgICAgICAgdHlwZSA9IGMoImN1bWluYyIsICJzdXJ2aXZhbCIsICJybWVhbiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgZm9ybXVsYS5jZW5zb3JpbmcgPSBOVUxMLCBpcGN3Lm1ldGhvZCA9IE5VTEwpew0KICBtYXJnZm9ybXVsYSA8LSB1cGRhdGUuZm9ybXVsYShmb3JtdWxhLCAuIH4gMSkNCiAgbXIgPC0gbW9kZWwucmVzcG9uc2UobW9kZWwuZnJhbWUobWFyZ2Zvcm11bGEsIGRhdGEgPSBkYXRhKSkNCiAgDQogIG1hcmdpbmFsLmVzdGltYXRlIDwtIHN1cnZpdmFsOjpzdXJ2cmVnKG1hcmdmb3JtdWxhLCBkYXRhID0gZGF0YSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpc3QgPSAid2VpYnVsbCIpDQogIHRoZXRhIDwtIHB3ZWlidWxsKHRpbWUsIHNoYXBlID0gMSAvIG1hcmdpbmFsLmVzdGltYXRlJHNjYWxlLCANCiAgICAgICAgICAgICAgICAgICAgc2NhbGUgPSBleHAobWFyZ2luYWwuZXN0aW1hdGUkY29lZmZpY2llbnRzWzFdKSkNCiAgDQogIHRoZXRhLmkgPC0gc2FwcGx5KDE6bnJvdyhkYXRhKSwgZnVuY3Rpb24oaSkgew0KICAgIA0KICAgIG1lIDwtIHN1cnZpdmFsOjpzdXJ2cmVnKG1hcmdmb3JtdWxhLCBkYXRhID0gZGF0YVstaSwgXSwgZGlzdCA9ICJ3ZWlidWxsIikNCiAgICBwd2VpYnVsbCh0aW1lLCBzaGFwZSA9IDEgLyBtZSRzY2FsZSwgDQogICAgICAgICAgICAgICAgICAgIHNjYWxlID0gZXhwKG1lJGNvZWZmaWNpZW50c1sxXSkpDQogIA0KICAgIA0KICB9KQ0KICANCiAgUE9pIDwtIHRoZXRhICArIChucm93KGRhdGEpIC0gMSkgKiAodGhldGEgLSB0aGV0YS5pKQ0KICBQT2kNCn0NCmBgYA0KDQoNCk5vdyBsZXQgdXMgdHJ5IGl0IG91dCBieSBwYXNzaW5nIGl0IHRvIHRoZSBgY3VtaW5jZ2xtYCBmdW5jdGlvbiBhbmQgY29tcGFyZSB0byB0aGUgZGVmYXVsdCBpbmRlcGVuZGVuY2UgZXN0aW1hdG9yOiANCg0KYGBge3J9DQpmaXRwYXJhIDwtIGN1bWluY2dsbShTdXJ2KHRpbWUsIHN0YXR1cykgfiByeCArIHNleCArIGFnZSwgdGltZSA9IDI1MDAsIA0KICAgICAgICAgICAgICAgICAgbW9kZWwuY2Vuc29yaW5nID0gcHNldWRvX3BhcmFtZXRyaWMsIA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KZml0ZGVmIDwtIGN1bWluY2dsbShTdXJ2KHRpbWUsIHN0YXR1cykgfiByeCArIHNleCArIGFnZSwgdGltZSA9IDI1MDAsIA0KICAgICAgICAgICAgICAgICAgbW9kZWwuY2Vuc29yaW5nID0gImluZGVwZW5kZW50IiwgDQogICAgICAgICAgICAgICAgICBkYXRhID0gY29sb24pDQprbml0cjo6a2FibGUoc2FwcGx5KGxpc3QocGFyYW1ldHJpYyA9IGZpdHBhcmEsIGRlZmF1bHQgPSBmaXRkZWYpLCANCiAgICAgICBjb2VmZmljaWVudHMpKQ0KYGBgDQoNCllvdSBjYW4gYWxzbyByZWZlciB0byB0aGUgZnVuY3Rpb24gd2l0aCBhIHN0cmluZywgb21pdHRpbmcgdGhlICJwc2V1ZG9fIiBwcmVmaXgsIGlmIHlvdSB3aXNoLCBlLmcuLCANCg0KYGBge3IsIGV2YWwgPSBGQUxTRX0NCmZpdDEgPC0gY3VtaW5jZ2xtKFN1cnYodGltZSwgc3RhdHVzKSB+IHJ4ICsgc2V4ICsgYWdlLCB0aW1lID0gMjUwMCwgDQogICAgICAgICAgICAgICAgICBtb2RlbC5jZW5zb3JpbmcgPSAicGFyYW1ldHJpYyIsIA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KYGBgDQoNCg0KPC9kZXRhaWxzPg0KDQoNCiMjIyBFeGFtcGxlIDI6IGluZmluaXRlc2ltYWwgamFja2tuaWZlDQoNCldoZW4gdGhlIHN1cnZpdmFsIHBhY2thZ2UgdmVyc2lvbiAzLjAgd2FzIHJlbGVhc2VkLCBpdCBiZWNhbWUgcG9zc2libGUgdG8gZ2V0IHRoZSBpbmZsdWVuY2UgZnVuY3Rpb24gdmFsdWVzIHJldHVybmVkIGZyb20gc29tZSBlc3RpbWF0aW9uIGZ1bmN0aW9ucy4gVGhlc2UgZWZmaWNpZW50IGluZmx1ZW5jZSBmdW5jdGlvbnMgYXJlIHVzZWQgaW4gdGhlIHZhcmlhbmNlIGNhbGN1bGF0aW9ucywgYW5kIHRoZXkgYXJlIHJlbGF0ZWQgdG8gcHNldWRvIG9ic2VydmF0aW9ucy4gTW9yZSBpbmZvcm1hdGlvbiBpcyBhdmFpbGFibGUgaW4gdGhlICJwc2V1ZG8uUm53IiB2aWduZXR0ZSBvZiB0aGUgZGV2ZWxvcG1lbnQgdmVyc2lvbiBvZiBzdXJ2aXZhbC4gVGhpcyBmZWF0dXJlIGhhcyBiZWVuIGluY29ycG9yYXRlZCBpbnRvIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBgZXZlbnRnbG1gLCBhdmFpbGFibGUgaW4gdGhlIGBwc2V1ZG9faW5mamFja2AgbW9kdWxlLiANCg0KDQpCZWxvdyBoZXJlIGlzIGEgc2ltcGxpZmllZCB2ZXJzaW9uLiBVc2UgdGhpcyBhcyBpbnNwaXJhdGlvbiB0byBjcmVhdGUgYSBtb2R1bGUgZm9yIGFuIGVzdGltYW5kIG9mIGludGVyZXN0IGluIGEgbXVsdGktc3RhdGUgbW9kZWwgKHNheSB0aGUgaWxsbmVzcyBkZWF0aCBtb2RlbCkuIA0KDQpgYGB7cn0NCnBzZXVkb19pbmZqYWNrIDwtIGZ1bmN0aW9uKGZvcm11bGEsIHRpbWUsIGNhdXNlID0gMSwgZGF0YSwNCiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBjKCJjdW1pbmMiLCAic3Vydml2YWwiLCAicm1lYW4iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgIGZvcm11bGEuY2Vuc29yaW5nID0gTlVMTCwgaXBjdy5tZXRob2QgPSBOVUxMKSB7DQogIA0KICBtYXJnaW5hbC5lc3RpbWF0ZTIgPC0gc3Vydml2YWw6OnN1cnZmaXQodXBkYXRlLmZvcm11bGEoZm9ybXVsYSwgLiB+IDEpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdGEsIGluZmx1ZW5jZSA9IFRSVUUpDQogICAgIHRkZXggPC0gc2FwcGx5KHRpbWUsIGZ1bmN0aW9uKHgpIG1heCh3aGljaChtYXJnaW5hbC5lc3RpbWF0ZTIkdGltZSA8PSB4KSkpDQogICAgIHBzdGF0ZSA8LSBtYXJnaW5hbC5lc3RpbWF0ZTIkc3Vydlt0ZGV4XQ0KICAgICAjIyBTKHQpICsgKG4pW1ModCkgLVNfey1pfSh0KV0NCiAgICAgUE9pIDwtIG1hdHJpeChwc3RhdGUsIG5yb3cgPSBtYXJnaW5hbC5lc3RpbWF0ZTIkbiwgbmNvbCA9IGxlbmd0aCh0aW1lKSwgYnlyb3cgPSBUUlVFKSArDQogICAgICAgICAobWFyZ2luYWwuZXN0aW1hdGUyJG4pICoNCiAgICAgICAgIChtYXJnaW5hbC5lc3RpbWF0ZTIkaW5mbHVlbmNlLnN1cnZbLCB0ZGV4XSkNCiAgICAgDQogICAgIFBPaQ0KfQ0KYGBgDQoNCk5vdGUgdGhhdCB0aGlzIGNvbXB1dGVzIHBzZXVkbyBvYnNlcnZhdGlvbnMgZm9yIHN1cnZpdmFsLCByYXRoZXIgdGhhbiB0aGUgY3VtdWxhdGl2ZSBpbmNpZGVuY2UsIHNvIHRvIGNvbXBhcmUgd2UgY2FuIHVzZSB0aGUgc3Vydml2YWwgPSBUUlVFIG9wdGlvbi4gTm93IHdlIHRyeSBpdCBvdXQNCg0KYGBge3J9DQpmaXRpbmYgPC0gY3VtaW5jZ2xtKFN1cnYodGltZSwgc3RhdHVzKSB+IHJ4ICsgc2V4ICsgYWdlLCB0aW1lID0gMjUwMCwgDQogICAgICAgICAgICAgICAgICBtb2RlbC5jZW5zb3JpbmcgPSAiaW5mamFjayIsIA0KICAgICAgICAgICAgICAgICAgc3Vydml2YWwgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgZGF0YSA9IGNvbG9uKQ0KZml0ZGVmc3VydiA8LSBjdW1pbmNnbG0oU3Vydih0aW1lLCBzdGF0dXMpIH4gcnggKyBzZXggKyBhZ2UsIHRpbWUgPSAyNTAwLCANCiAgICAgICAgICAgICAgICAgIHN1cnZpdmFsID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBjb2xvbikNCmtuaXRyOjprYWJsZShzYXBwbHkobGlzdChpbmZqYWNrID0gZml0aW5mLCBkZWZhdWx0ID0gZml0ZGVmc3VydiksIA0KICAgICAgIGNvZWZmaWNpZW50cykpDQpgYGANCg==