Kathy
Kathy

Reputation: 194

How to calculate days until next occurrence?

Have asked another question using a similar dataset, but different question -

I have a dataset that is a list of dates, followed by a column that either contains "R" for regular or "S" for special:

date <- c('01/01', '01/02', '01/03', '01/04', '01/05', '01/06', '01/07', '01/08', '01/09')

day <- c('S', 'R', 'R', 'R', 'R', 'S', 'R', 'R', 'S')

data <- data.frame(date, day)

It looks like this:

date . . . day

01/01. . . S

01/02. . . R

01/03. . . R

01/04. . . R

01/05. . . R

01/06. . . S

01/07. . . R

01/08. . . R

01/09. . . S

....

Now I'm trying to add a column that would indicate how many days there are until the next "special" day. So, for the shown data, it'd be 0 (01/01 is special), 4 (01/02 is 4 days away from the next special day, 01/06), 3, 2, 1, 0 (01/06 is special), etc.

Thanks!

Upvotes: 1

Views: 434

Answers (2)

Ben
Ben

Reputation: 30474

Here is a dplyr approach. You can use cumsum to group the days prior to a special day together, and then countdown by taking the number of days n() and subtract the row number row_number() in the group.

library(dplyr)

data %>%
  group_by(grp = cumsum(lag(day, default = first(day)) == 'S')) %>%
  mutate(days_until = n() - row_number())

Output

# A tibble: 9 x 4
# Groups:   grp [3]
  date  day     grp days_until
  <fct> <fct> <int>      <int>
1 01/01 S         1          0
2 01/02 R         2          4
3 01/03 R         2          3
4 01/04 R         2          2
5 01/05 R         2          1
6 01/06 S         2          0
7 01/07 R         3          2
8 01/08 R         3          1
9 01/09 S         3          0

Upvotes: 0

Sotos
Sotos

Reputation: 51582

Here is an idea via base R. Use cumsum to create groups when day is S, take the length sequence of each and replace the maximum value (that corresponds to S) with 0, i.e.

i1 <- cumsum(data$day == 'S')
data$res <- ave(i1, i1, FUN = function(i) { i2 <- seq_along(i); rev(replace(i2, max(i2), 0)) })

which gives,

   date day res
1 01/01   S   0
2 01/02   R   4
3 01/03   R   3
4 01/04   R   2
5 01/05   R   1
6 01/06   S   0
7 01/07   R   2
8 01/08   R   1
9 01/09   S   0

Upvotes: 1

Related Questions