knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) library("JMbayes2")
The first step in fitting a joint model for competing events in JMbayes2 is to prepare the data for the event process. If there are $K$ competing events, each subject must have $K$ rows, one for each possible cause. The observed event time $T_i$ of each subject is repeated $K$ times, and there are two indicator variables, namely one identifying the cause and one indicating whether the corresponding event type is the one that occurred. Standard survival datasets that include a single row
per patient can be easily transformed to the competing risks long format using the function crisk_setup()
. This function accepts as main arguments the survival data in the standard format with a single row per patient, the name of the status variable, and the level in this status variable that corresponds to censoring. We illustrate the use of this function in the PBC data, in which we treat as competing risks transplantation and death:
pbc2.id[pbc2.id$id %in% c(1, 2, 5), c("id", "years", "status")] pbc2.idCR <- crisk_setup(pbc2.id, statusVar = "status", censLevel = "alive", nameStrata = "CR") pbc2.idCR[pbc2.idCR$id %in% c(1, 2, 5), c("id", "years", "status", "status2", "CR")]
Note that each patient is now represented by two rows (we have two possible causes of
discontinuation from the study, death and transplantation), the event time variable years
is identical in both rows of each patient, variable CR
denotes the cause for the specific line of the long dataset, and variable status2
equals 1 if the corresponding event occurred.
For the event process, we specify cause-specific relative risks models. Using dataset pbc2.idCR
, we fit the corresponding cause-specific Cox regressions by including the interaction terms of age and treatment with variable CR
, which is treated as a stratification variable using the strata()
function:
CoxFit_CR <- coxph(Surv(years, status2) ~ (age + drug) * strata(CR), data = pbc2.idCR)
We include two longitudinal outcomes for the longitudinal process, namely serum bilirubin and the prothrombin time. For the former, we use quadratic orthogonal polynomials in the fixed- and random-effects parts, and for the latter, linear evolutions:
fm1 <- lme(log(serBilir) ~ poly(year, 2) * drug, data = pbc2, random = ~ poly(year, 2) | id) fm2 <- lme(prothrombin ~ year * drug, data = pbc2, random = ~ year | id)
To specify that each longitudinal outcome has a separate association coefficient per competing risk, we define the corresponding functional forms:
CR_forms <- list( "log(serBilir)" = ~ value(log(serBilir)):CR, "prothrombin" = ~ value(prothrombin):CR )
Finally, the competing risks joint model is fitted with the following call to jm()
(due to the complexity of the model, we have increased the number of MCMC iterations and the burn-in period per chain):
jFit_CR <- jm(CoxFit_CR, list(fm1, fm2), time_var = "year", functional_forms = CR_forms, n_iter = 25000L, n_burnin = 5000L, n_thin = 5L) summary(jFit_CR)
Based on the fitted competing risks joint model, we will illustrate how (dynamic) predictions can be calculated for the cause-specific cumulative risk probabilities. We will show these calculations for Patient 81 from the PBC dataset as an example. First, we extract the data on this subject.
ND_long <- pbc2[pbc2$id == 81, ] ND_event <- pbc2.idCR[pbc2.idCR$id == 81, ] ND_event$status2 <- 0 ND <- list(newdataL = ND_long, newdataE = ND_event)
The first line extracts the longitudinal measurements, and the second line extracts the event times per cause (i.e., death and transplantation). This patient died at 6.95 years, but to make the calculation of cause-specific cumulative risk more relevant, we presume that she did not have the event, and we set the event status variable status2
to zero. The last line combines the two datasets in a list. Note: this last step is a prerequisite from the predict()
method for competing risks joint model. That is, the datasets provided in the arguments newdata
and newdata2
need to be named lists with two components. The first component needs to be named newdataL
and contain the dataset with the longitudinal measurements. The second component needs to be named newdataE
and contain the dataset with the event information.
The predictions are calculated using the predict()
method. The first call to this function calculates the prediction for the longitudinal outcomes at the times provided in the times
argument, and the second call calculates the cause-specific cumulative risk probabilities. By setting the argument return_newdata
to TRUE
in both calls, we can use the corresponding plot()
method to depict the predictions:
predLong <- predict(jFit_CR, newdata = ND, return_newdata = TRUE, times = seq(6.5, 15, length = 25)) predEvent <- predict(jFit_CR, newdata = ND, return_newdata = TRUE, process = "event") plot(predLong, predEvent, outcomes = 1:2, ylim_long_outcome_range = FALSE, col_line_event = c("#03BF3D", "#FF0000"), fill_CI_event = c("#03BF3D4D", "#FF00004D"), pos_ylab_long = c(1.5, 11.5)) legend(x = 8.1, y = 0.45, legend = levels(pbc2.idCR$CR), lty = 1, lwd = 2, col = c("#03BF3D", "#FF0000"), bty = "n", cex = 0.8)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.