I have a dataset of patient visits at a clinic. Each individual patient can visit on multiple occasions. Each patient is identified by a study_id and each visit by an illness_id. I want to iteratively filter the dataframe so that a visit that occurs within 28 days of a previous visit is removed.
I cannot simply calculate the interval between all visits and then remove those which occur within 28 days. The intervals need to be calculated iteratively as the dataframe is filtered.
In the example below you can see patient 0003 presented three times. Visit 1 is always retained. Visit 2 should be removed as it occurred 7 days after Visit 1. Once Visit 2 is removed, Visit 3 would occur 29 days after Visit 1 and so should be retained. However if I calculate all the intervals and then filter out any visits with an interval of 28 days or less, both Visits 2 and 3 would be removed (because Visit 2 occurred 7 days after Visit 1 and Visit 3 occurred 22 days after Visit 2).
| study_id | illness_id | illness_date |
|---|---|---|
| 0001 | 000103/12/2007 | 2007/12/03 |
| 0002 | 000224/03/2008 | 2008/03/24 |
| 0002 | 000226/04/2008 | 2008/04/26 |
| 0002 | 000217/07/2008 | 2008/07/17 |
| 0002 | 000221/08/2008 | 2008/08/21 |
| 0002 | 000225/08/2008 | 2008/08/25 |
| 0003 | 000329/09/2008 | 2008/09/29 |
| 0003 | 000306/10/2008 | 2008/10/06 |
| 0003 | 000328/10/2008 | 2008/10/28 |
The correctly filtered dataframe should be:
| study_id | illness_id | illness_date |
|---|---|---|
| 0001 | 000103/12/2007 | 2007/12/03 |
| 0002 | 000224/03/2008 | 2008/03/24 |
| 0002 | 000226/04/2008 | 2008/04/26 |
| 0002 | 000217/07/2008 | 2008/07/17 |
| 0002 | 000221/08/2008 | 2008/08/21 |
| 0003 | 000329/09/2008 | 2008/09/29 |
| 0003 | 000328/10/2008 | 2008/10/28 |
Thanks for any help - I am new to R and am struggling to get my head around iteration and loops. If there is a simple solution involving dplyr filter that would be great.
IN RESPONSE TO SOME SUGGESTIONS BELOW I AM POSTING ANOTHER EXAMPLE TO TRY AND MAKE THE QUESTION CLEARER
The 'comparator' row cannot be fixed at the first visit for each patient. It needs to roll through the dataframe as the filtering is done iteratively. Sorry if this was not clear in the OP. Here is an eg where rows 2, 3 and 5 should be removed, and rows 1, 4 and 6 should be retained.
Row 2 is 8 days after row 1, so is removed. Row 3 is 26 days after row 1, so is removed. Row 4 is 41 days after row 1, so is retained and becomes the comparator for subsequent visits for this patient. Row 5 is 6 days after row 4, so is removed. Row 6 is 31 days after row 4 so is retained and becomes the comparator for subsequent visits for this patient.
| study_id | illness_id | illness_date |
|---|---|---|
| 0001 | 000119/12/2007 | 19/12/2007 |
| 0001 | 000127/12/2007 | 27/12/2007 |
| 0001 | 000114/01/2008 | 14/01/2008 |
| 0001 | 000129/01/2008 | 29/01/2008 |
| 0001 | 000104/02/2008 | 04/02/2008 |
| 0001 | 000129/02/2008 | 29/02/2008 |
Here is the v elegant solution provided by @sbarbit - sincere thanks!!
df1 <- df |>
arrange(study_id, illness_date) |>
mutate(comparator = purrr::accumulate(illness_date,~ifelse(.y - .x > 28, .y,.x))) |>
mutate(daydiff = illness_date - lag(comparator, 1,0)) |>
mutate(daydiff = as.numeric(daydiff)) |>
filter(daydiff > 28)