0

In a Cox regression framework, I'd like to implement piecewise continuous time-dependent coefficients. This is for variable that do not satisify the PH assumption.

In this vignette https://cran.r-project.org/web/packages/survival/vignettes/timedep.pdf, there are examples for step functions (p.17), and coefficient with some functional form (p.20). What I'd like is to somehow have a piecewise relationship. Using the example provided in the vignette:

library(survival)
vfit <- coxph(Surv(time, status) ~ trt + prior + karno, veteran)
zp <- cox.zph(vfit, transform= function(time) log(time +20))

## Step functions
vet2 <- survSplit(Surv(time, status) ~ ., data= veteran, cut=c(90, 180),
                  episode= "tgroup", id="id")
vfit2 <- coxph(Surv(tstart, time, status) ~ trt + prior +
               karno:strata(tgroup), data=vet2)

## Functional form
vfit3 <- coxph(Surv(time, status) ~ trt + prior + karno + tt(karno),
               data=veteran,
               tt = function(x, t, ...) x * log(t+20))
plot(zp[3])
abline(coef(vfit3)[3:4], col=2)

From the plot (also on p.21 in the vignette), we might argue that we could have a similar but inverted trend from approx. Time=200. I've tried but without success.

First tried directly with a piecewise function with the tt argument but it does not give two sets of coefficents, only one coef for karno and one for tt(karno). I mean we should have something like ax+b for t<200 and cx+d for t>=200

vfit3 <- coxph(Surv(time, status) ~ trt + prior + karno + tt(karno),
               data=veteran,
               tt = function(x, t, t1, t2, ...) x * log(t1+20) * (t<200) + 
                                        x * t2 * (t>=200))

So in a second step, I tried to mix both step functions with some functional form for each. Meaning to split the data in two time periods as for step functions and then fit a function in each. But gives error.

vfit3 <- coxph(Surv(tstart, time, status) ~ trt + prior + 
               (karno + tt(karno)):strata(tgroup),
               data=vet2,
               tt = function(x, t, ...) x * log(t+20) * (t<200) - 
                                        x * t * (t>=200))

Does someone knows how to implement this?


EDIT:

This is what I've come up with

library(survival)

## Original model
m1 <- coxph(formula = Surv(time, status) ~ trt + prior + karno, 
            data = veteran)

## Transform to long format as in the link
vet1 <- survSplit(Surv(time, status)~., data = veteran, id = "id",
                  cut = unique(veteran$time))

## Add a grouping variable (strata) for time before 200 days and after.
vet1$tgroup <- ifelse(vet1$time < 200, 1, 2)

## Add a time-transform function 
## Here it is the same function for both strata, but they could be different
## e.g. ifelse(vet1$time < 200, f1(time), f2(time))
## Actually not sure, as we need to be careful with the time scale... Anyway
vet1$time1 <- log(vet1$time + 20)

## Same model as in the link, but then add an interaction with the strata
m2 <- coxph(formula = Surv(tstart, time, status)~
            trt + prior + (karno + karno:time1):strata(tgroup), data = vet1)

## Some plots as in the vignette
zp <- cox.zph(m1, transform = function(time) log(time +20))
plot(zp[3])
abline(coef(m2)[c(3,5)], col="tomato")
abline(coef(m2)[c(4,6)], col="tomato")
user3631369
  • 329
  • 1
  • 12
  • I think there are spline functions that are piecewise linear and continuous. Have you tried one of them? – IRTFM Jan 30 '22 at 16:01
  • I wasn't aware of their existence. I will have a look. In the meantime I've used the method from https://stackoverflow.com/questions/45870975/how-to-model-interaction-of-covariate-with-time-when-proportionality-assumption. I've transformed to long-format and then could add a "standard" interaction as in linear regression for example. This way I managed to define a piecewise function. But not sure if it is correct... – user3631369 Feb 02 '22 at 19:03
  • Looks like option 3 in that answer is automatically a piecewise estimate. The tutorial at the link in that question has worked example that shows how it compares to Therneau’s example solution in the survival package vignette. – IRTFM Feb 02 '22 at 23:59
  • I don't think it is piecewise. It defines a continuous function over the range of time values, without allowing for breakpoints. By piecewise I mean it could be not continuous. But yes it compares to the timedep vignette and looks it gives same outputs. Thanks for the time! – user3631369 Feb 03 '22 at 13:31
  • I think of “piecewise” as including step functions. – IRTFM Feb 03 '22 at 15:57
  • I've edited my question, would be easier! – user3631369 Feb 04 '22 at 08:26

0 Answers0