# help with getting my data set up for cox ph (time dependent) to predict within time

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.

EDIT: TOY EXAMPLE FOR REFERENCE (DIFFERENT FROM THE TABLE ABOVE)

#CREATE DATAFRAME (TIME VARYING IS ALREADY CODED)
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))


#CREATE SURVIVE OBJECT

surv_object1 <- Surv(time=df$$time0, time2 = df$$time1, event = df$death) #COX MODEL fit.cox <- coxph(surv_object1 ~gender, data = df) #PREDICT results<- survfit(fit.cox, newdata=df) summary(results)  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) EDIT 2: 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. library(survival) #CREATE DATAFRAME (TIME VARYING IS ALREADY CODED) 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)
#COX MODEL
fit.cox <- coxph(surv_object1 ~tdc, data = df)
#PREDICT
results<- survfit(fit.cox, newdata=df)
summary(results)

$$$$

• 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.
– EdM
Aug 16, 2020 at 13:58
• thank you. I added a toy exampl that can be copy and pasted to look. I'm using survfit to do the prediction. Aug 16, 2020 at 18:05
• 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.
– EdM
Aug 16, 2020 at 19:39
• 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 Aug 17, 2020 at 0:16

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)

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

2
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

3
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.

• 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. Aug 17, 2020 at 19:37
• @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.
– EdM
Aug 17, 2020 at 21:44