Reputation: 194
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
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
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