Search code examples
rdplyr

Relative Time Index for Sequences of Treatment in R


I am working in R, and I would like to create a relative time index for the case when a treatment can turn on and off for an individual. Thus, the index would count upwards from some negative number until 0, when treatment becomes a 1 and will count up as long as treatment remains at 1 before resetting. It simplest to explain what I need using an example.

Suppose I have data that looks like this:

df <- data.frame(id = c(1,1,1,1,1,1,1,1,1,1,1,2,2,2,2), treatment = c(0,0,1,1,0,0,0,1,1,1,0,0,1,1,1))

I would like to get to the following result:

  id treatment relative_time
1     1         0            -2
2     1         0            -1
3     1         1             0
4     1         1             1
5     1         0            -3
6     1         0            -2
7     1         0            -1
8     1         1             0
9     1         1             1
10    1         1             2
11    1         0             .
12    2         0            -1
13    2         1             0
14    2         1             1
15    2         1             2

I have seen that the following code works for when you have treatment occurring once per individuals, but sadly I have not been able to find a way to adapt it to my case:

df  %>%
  group_by(id) %>%
  mutate(relative_time = seq_along(treatment) - which(treatment %in% 1))

Any help would be appreciated!


Solution

  • You could use dplyr library to first create a new grouping variable using cumsum() to detect value changes, then sequence each group 0,1,2...(n-1) when treatment is 1, and -n+0, -n+1, ... -1 when treatment is 0,

    library(dplyr)
    
    df %>%
      mutate(
        g = cumsum(treatment != lag(treatment, default = TRUE)),
        .by = id
      ) |>
      mutate(
        relative_time = seq_along(g) - 1 + ifelse(treatment, 0,  -length(g)),
        .by = c(id, g)
      ) |>
      select(-g)
    

    output

    id treatment relative_time
    1   1         0            -2
    2   1         0            -1
    3   1         1             0
    4   1         1             1
    5   1         0            -3
    6   1         0            -2
    7   1         0            -1
    8   1         1             0
    9   1         1             1
    10  1         1             2
    11  1         0            -1
    12  2         0            -1
    13  2         1             0
    14  2         1             1
    15  2         1             2