I have many observations of data, and survival ranges from month1 to month24. i.e some patients will survive 1month, 2month, 3month, or go all the way to month24. For each observation, I'm trying to get monthly predictions, up to month24.

A cox-ph output may show something like the table below [![enter image description here][1]][1]

However, this analysis has time dependent covariate where the there's a change every 12 month mark. To address this, I reformated my data to tstart tstop format, and now, my survival rate looks like this after I fit the cox model again

ph<- tmerge(data, data, id=observation, tstart=0, tstop=survived_through)

I guess ID observation 1 makes sense since I see gradually decreasing probabilities of survival.

Observation 2 is where I'm having issues. From month1 to month12, I still see gradually decreasing probabilities, but from month 12-24, it "resets" to 96% survival. It appears as if it is treating each row of observation 2 as different observations. How would I go about "connecting" observation 2 so it will show decreasing probabilities from 0 to 24?

Is it reasonable to say that the probabilities from 0 to 12 of tstart/tstop[0-12] is correct, and the probability of 12 to 24 of tstart/tstop[12-24] is the 'adjusted probability' after adding the time varying covariate (and it is also accounting for the time varying covariate from 0 to 12) and I can just "chain them" together?

I'm using R and the survival package.


df <- data.frame("id" = c(1,2,2,3,3,3), "gender" = c("m","f","f","m","m","m"), "time0" = c(0,0,1,0,5,8), "time1" = c(1,1,4,5,8,10), "death" = c(1,0,1,0,0,1))


surv_object1 <- Surv(time=df$time0, time2 = df$time1, event = df$death)
fit.cox <- coxph(surv_object1 ~gender, data = df)
results<- survfit(fit.cox, newdata=df)

scoring the data to get the predicted probabilities, I get survival1...survival2...survival6 denoting each observation, but you see the estimate don't gradually decline from survival2 to survival3(survival2 and survival3 are still the same observation just at different time points)


Sorry. I think you can ignore my original table. That was used just for illustrative purposes. Here's an extension of the toy example w/ time covariates. "tdc" is the time varying covariate that happens every 12 months.


df <- data.frame("id" = c(1,2,2,3,3,3), "gender" = c("m","f","f","m","m","m"), 
                 "time0" = c(0,0,12,0,24,36), 
                 "time1" = c(1,12,24,24,36,48), "death" = c(1,0,1,0,0,1),
                 "tdc" = c(1.2,1.0,1.2,2.1,1.4,1.6))

surv_object1 <- Surv(time=df$time0, time2 = df$time1, event = df$death)
fit.cox <- coxph(surv_object1 ~tdc, data = df)
results<- survfit(fit.cox, newdata=df)

  • 1
    $\begingroup$ Could you please show the code that produces these specific tables? That seems to be from some type of predict() function applied to your model, and I suspect that the problem is in how that particular function is being invoked. $\endgroup$
    – EdM
    Aug 16, 2020 at 13:58
  • $\begingroup$ thank you. I added a toy exampl that can be copy and pasted to look. I'm using survfit to do the prediction. $\endgroup$
    – semidevil
    Aug 16, 2020 at 18:05
  • $\begingroup$ The toy example you now provide doesn't have a time-varying covariate, so the way the results are displayed does make sense: survival2 and survival3 represent the same individual2 with the same covariate, so the survival predictions at event times are necessarily the same for that individual. Also, the tables produced by your example seems to present different information from the tables that were in a previous version of the question. So it's still hard to see what your specific question is. $\endgroup$
    – EdM
    Aug 16, 2020 at 19:39
  • $\begingroup$ my bad. I added another comment on my original post under edit 2. It may be just that I dont know how to set up my data, but would appreciate any insight $\endgroup$
    – semidevil
    Aug 17, 2020 at 0:16

1 Answer 1


Although incorporation of time-dependent covariates is an important use case for Cox models, you have to be very careful in how you set up and interpret them.

First, make sure you have the time-dependent covariate values presented and interpreted correctly. For the data following your EDIT 2:

> df
  id gender time0 time1 death tdc
1  1      m     0     1     1 1.2
2  2      f     0    12     0 1.0
3  2      f    12    24     1 1.2
4  3      m     0    24     0 2.1
5  3      m    24    36     0 1.4
6  3      m    36    48     1 1.6

the value of tdc=2.1 for id=3 is assumed to hold from time=0 through and including time=24. So for evaluating the event for id=2 at time=24, the value of tdc used for id=3 is 2.1, not 1.4. As the time-dependent vignette puts it on page 2:

One way to think of this is that all changes for a given day (covariates or status) are recorded at the start of the next interval.

So make sure that your data are coded with that in mind.

Second, when you perform survfit() based on a model and a (potentially new) set of data to get predictions, you have to make sure that you provide the correct information about the time-dependencies within the model. If you simply perform survfit() the way that you did on those example data, you get:

> summary(results)
Call: survfit(formula = fit.cox, newdata = df)

 time n.risk n.event survival1 survival2 survival3 survival4 survival5 survival6
    1      3       1    0.6956   0.54939    0.6956     0.963     0.803     0.875
   24      2       1    0.2814   0.12339    0.2814     0.875     0.464     0.628
   48      1       1    0.0185   0.00138    0.0185     0.658     0.089     0.231

As you provided no information about which data rows corresponded to which individual, you got separate predictions for each row based on its own value of tdc. For example, survival1 and survival3 are identical as tdc=1.2 for both rows 1 and 3, and the survival values at any time increase with increasing values of tdc, consistent with the Hazard Ratio of 0.08 reported by summary(fit.cox).

If you want to get predictions about individual cases with time-dependent covariates, you need to provide information about how the cases line up with the data rows. With the survival package you do that with an id parameter setting to get id-specific predictions at each event time in the original model:

> results.tdc<- survfit(fit.cox, newdata=df,id=id)
> summary(results.tdc)
Call: survfit(formula = fit.cox, newdata = df, id = id)

 time n.risk n.event survival std.err lower 95% CI upper 95% CI 
    1      3       1    0.696   0.260        0.334            1 

 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    1      3       1    0.549   0.347       0.1593            1
   24      2       1    0.222   0.243       0.0261            1

 time n.risk n.event survival std.err lower 95% CI upper 95% CI
    1      3       1    0.963   0.112       0.7667            1
   24      2       1    0.875   0.307       0.4399            1
   48      1       1    0.322   0.361       0.0358            1

With this explicit time-dependent structure, survfit() has now prevented you from making survival predictions beyond the times for which you provided it information. No predictions for any individual are made beyond that individual's last time value. If you, say, wanted a prediction for a patient like id=1 for times beyond time=1 your newdata would need to be set up in a way to allow for that.

Finally, be very very wary about predictions that depend on time-dependent covariates. It's all too easy to slip into a self-fulfilling "prediction" in which a time-dependent covariate value is simply a proxy for already having survived a long time. Be on guard against such survivorship bias.

  • $\begingroup$ thank you! to your comment about setting up the data to see beyond time=1 for id=1, how would I want to set it up? also....My end goal is to see probability for each time increment. For example, for ID 1, i want to see up to time=12, but I want to see time1, time2, time3, time4......time 12. $\endgroup$
    – semidevil
    Aug 17, 2020 at 19:37
  • $\begingroup$ @semidevil in newdata you could just set the final time for id1 to some large time (and maybe omit the event indicator; don't think you need that in newdata). The problem is you don't know the time course of tdc for id1 for time >1. So how can you reliably make a prediction for that patient beyond then? Your prediction would be based on an assumption that tdc=1.2 for id1for all subsequent times. The alternative is to assume specific values of tdc for later times. This is one reason why you have to think very carefully about what predictions mean with time-varying covariates. $\endgroup$
    – EdM
    Aug 17, 2020 at 21:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.