I have a longitudinal data with exposure air pollution and outcome cardiovascular disease. The inclusion starts from 2010 to 2017 and then I followed until 2021. I have measurement of pollution from 1989 to 2021 as continues measures. I use a cox regression, pollution as time-varying covariate and I have left truncation. Then I use age as time (event age at CVD) and consider competing risk of death. Now, my question is how to deal with exposure (pollution) (I have multiple rows as exposure for each individual)? how can I use all information of my exposure and is it an issue that I have the information way back the inclusion?

  • $\begingroup$ @ EdM I appreciate your input. $\endgroup$
    – user358238
    Feb 2 at 11:26
  • $\begingroup$ The @ call-out only works if the individual is already in the corresponding thread of comments. I found this anyway. $\endgroup$
    – EdM
    Feb 2 at 14:00
  • $\begingroup$ I think I can help you with an pretty informative answer but I need you to be patient for some time (maybe days) as I am busy now. $\endgroup$
    – jmarkov
    Feb 5 at 15:37
  • $\begingroup$ Your pollution measurements are yearly averages? I mean do you have one air pollution value for each year from 1989 to 2021? $\endgroup$
    – jmarkov
    Feb 7 at 13:08

2 Answers 2


At each event time, the Cox mode uses the current values of the covariates for all those at risk of the event. That said, it's possible to devise new covariates that represent some aspect of the history of measured covariate values, like a running average perhaps weighted in some way with respect to time.

Your question thus requires you to apply your understanding of the subject matter. Is it today's air pollution that contributes to today's risk of CVD or death? I would guess not, except maybe in extreme circumstances. Is it lifetime exposure to pollution? Exposure over the previous 5 years? Or 10 years? Exposure during youth? If you want to use a Cox regression, you have to convert the history of exposure to some value that is related to today's risk of the event.

This might be better handled with a joint model of exposure and outcomes. I'm not an expert on that. For an introduction, look at these answers from Dimitris Rizopoulos, who has developed tools for such models, or this blog post.

  • $\begingroup$ @Dimitris Rizopoulos Dear Dimitris, your input is highly appreciated as well. $\endgroup$
    – user358238
    Feb 5 at 10:36
  • $\begingroup$ @user358238 as Dimitris Rizopoulos isn't already involved in this comment chain, using the @ here won't get his attention. It only works if you comment directly on one of his questions or answers, or if he has already commented on the question or answer that you are addressing. $\endgroup$
    – EdM
    Feb 5 at 13:02

The PhD I am currently working on focuses specifically on this topic so I think I can give you some good tips.

Important point:

If your outcome is incidence of cardiovascular diseases, then you do not need to define competing risks for death! It will be just a time-dependent Cox Proportional Hazard model (Cox PH). This is what you will also find in most of the literature.


If your air pollution data is yearly averages corresponding to each year between 1989 and 2021, then defining a time-varying Cox PH model will be quite simple. Very recently me and colleagues published a paper (open access) that I will use as reference to avoid creating multiple tables in the answer.

  1. Your "basic" cohort and outcome tables will need to look like Table 1a and 1b (you don't need Table 1c as you already have your exposure table). In Table 1a you have the basic cohort information, while in Table 1b you have the outcome. In Table 1a the "Last follow-up date" refers to the date your observation leaves the follow-up, that is due to censoring (observation , death or administrative end of the follow-up, which in your case is 31/12/2021).

    Also, I assume your exposure data (exposuredata dataset) looks more or less like this:

ID year exposure_value
1 1989 ...
1 1990 ...
  1. Now you need to merge Table 1a and 1b so that you still only have one row per subject. In some way, you need to select which outcome you are exactly interested in, in terms of ICD. This merge with give you a table like this (replace the ... with your dates):

Table 2:

ID Enrolment date Last follow-up date ICD outcome date
1 ... ... I25.1 ...

From Table 2 you need to define a new date column (new_exitdate) which will have values equal to either "Last to follow-up date" or "outcome date", whichever comes first. Also, you need to define an indicator for event (event): 1 if the observation has the event (cardiovascular disease) during the follow-up or 0 if he/she doesn't. Eventually, you will only need to have the following columns: ID, "enterdate" (which is equal to "Enrolment date"),"new_exitdate" and "event".

  1. Now you have Table 2 ready to be split so we can link the exposure to it! When I worked on this stuff the first time, I got my ispiration from this working example (particularly model B). To do the time splitting in R you can use a simple code:

     low<- year(min(table2$enterdate)); up<- year(max(table2$new_exitdata))
     cutyr <- low:up
     splitdata <- survSplit(Surv(enterdate, new_exitdate, event) ~., table2, cut=cutyr)

Now you have your splitted data which includes multiple rows per observation, each of which corresponds to an ID-year pair.

  1. You can simply merge splitdata with your exposure data :) by ID and year! ATTENTION: be careful in this moment because you can merge your exposure using the same year (e.g. assign 2010 exposure to 2010 time) but you can also do a different assignment, for instance you can assign the exposure of the previous year (e.g. assign 2009 exposure to 2010 time). You need to run some sensivity analyses to see how the effect changes when you change assignment. Remember: in no way you can assign future exposure to a time. For instance, if the time is 2010 you cannot assign 2011 exposure as it makes not sense!

Considering that you super long exposure data before the start of the study, you might be interested in using different exposure averages instead of single years. For instance, you want to assign 5-year or 10-year exposure average. Then you just need to define a 5-year average by row. For example for time 2010 you can assign averages of values from 2006 to 2010. There are some nice papers that looked how risk estimates change when you use averages for different exposure time frame (e.g. here) You can create averages across multiple years in R (with data.table) with something like this:

exposuredata<- exposuredata[, 5yrave:=rowMeans(Reduce(cbind, shift(exposure_value, 0:5))), by=ID]

To understand this part I recommend to study Figure 3 of the paper, which corresponds to the Definition of individual summaries for epidemiological studies (Step 3) section.

  1. You can run your cox model! The code will be something like this:

model<-coxph(Surv(enterdate,new_exitdate, event) ~ exposure + covariates, data)

I do not recommend using age as main time scale as you wish to do, rather I would control for it in the model using a spline term maybe. (something like ns(age, df=5)). However, in your splitdata dataset age needs to be calculated as difference between the birthdate and new_exitdata at each time point. There are other ways to control for it, such as stratifying by year of birth, but just ask if you need!

Also, remember that the selection of the covariate must relatively careful. Because I imagine your exposure is from outdoor predictions, then using area-level covariates (such as neighborhood deprivation) is recommded to account for confounding.

I think this is enough for now and I tried not too specific, but if you need details or clarifications on sometihng, ask and I can edit the answer. Also, there might be a few mistakes in the text, please just gently point them out. Cheers


Your Answer

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

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