# Which function of time to use in a Cox Regression for time-varying coefficients?

I have a Cox regression model where the outcome is a non-recurring event. Within the model, two categorical variables violate proportional hazards, and I have currently extended it to account for time-varying coefficients.

Using the survival package, I have split up the analysis time into multiple intervals per individual, and then created interactions between the variables violating PH and time using the tt() function.

However, I am getting very different results depending on which function of time I specify within the interaction. I am unclear as to why a certain function of time (e.g. log(t) vs t^2) might be preferred within this interaction. Is there a reason to choose one function over another?

• Please say more about why you have to "account for multiple time intervals for a single individual." Is this a repeated-events situation, are there time-varying covariate values, or something else? Also, please say more about just how you are including the "interaction ... with time" as improper implementation can lead to incorrect results. Please edit your question to include this information rather than responding in a comment, as comments are sometimes overlooked and can even be lost.
– EdM
Oct 18, 2020 at 17:46
• I've done as you have asked, and hopefully this will clarify it a bit further!
– Ryan
Oct 18, 2020 at 18:28

The time-dependent vignette for the survival package recommends examining the shape of the plot of scaled Schoenfeld residuals over time and using a function that captures the shape of that relationship; see Section 4.2 of the vignette. That's why different situations might be handled best by different functional forms for the change over time. For this continuous-time modeling approach, that Section shows how to overlay the tt() function result onto the plot of residuals, to see how well you have managed to model the time dependence. Sometimes a simple step function will work well enough, which is modeled instead by breaking the data into strata containing different epochs and allowing covariate:stratum interaction terms; see Section 4.1 of the vignette. You will have to examine your own results to decide which functional form to try.

With two predictors at issue for lack of proportional hazards, you will need to specify a list of functions for tt(), to handle the two invocations of the function in the model formula. Also, be very careful in your syntax. For example, although for the continuous-time modeling approach you are evaluating an interaction of your covariate with a function of time, you don't write it as a usual interaction in the main formula but rather include the tt() as a separate additive term in the formula, with the interaction specified as a product in the definition of tt(). In the example of Section 4.2 of the vignette:

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


Finally, unless you have time-dependent covariates or are using the time-epoch stratification approach to handle step-changes in coefficient values, with no more than one event per individual you don't need to split up the data into "multiple time intervals per individual" to model time-dependent coefficients.

• Interesting. Thank you! Looking at the vignette, then, the plot produces a plot of residuals, and I should try to create a function of time that relates to that plot?
– Ryan
Oct 18, 2020 at 20:54
• @Ryan yes, that's the idea. Be careful, as the standard output from cox.zph() is based on a default time axis that is related to Kaplan-Meier times, not to absolute time. You might want to adjust the choice of time axis to represent absolute time instead.
– EdM
Oct 18, 2020 at 20:57
• Can you expand on what you mean by absolute time, and how that might be implemented?
– Ryan
Oct 18, 2020 at 21:16
• @Ryan if you look carefully at the plots in the vignette or in plots generated from the default transform="km" option for cox.zph(), you'll see that the values along the x-axis aren't evenly spaced the way you might expect. So in the call to cox.zph() specify the option transform="identity". Then the distribution of time values along the x-axis represents the actual time values (what I called "absolute" in my comment, which can't be edited now). That might make it easier to gauge the way that the coefficient is varying over time.
– EdM
Oct 18, 2020 at 21:29
• Great. This was very helpful. Now that I have this completed, however, my concern lies with interpretation of the coefficients, especially as time is manipulated. Any resources on the best way to do this?
– Ryan
Oct 18, 2020 at 21:57