Как рассчитать дни до следующего события? - PullRequest
2 голосов
/ 06 мая 2020

Задавали другой вопрос, используя аналогичный набор данных, но другой вопрос -

У меня есть набор данных, который представляет собой список дат, за которым следует столбец, содержащий либо «R» для обычных, либо «S» для 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)

Это выглядит так:

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

....

Теперь я пытаюсь добавить столбец, который бы указывал, сколько дней осталось до следующего «особого» дня. Таким образом, для показанных данных это будет 0 (01/01 является особенным), 4 (01/02 - 4 дня до следующего особого дня, 01/06), 3, 2, 1, 0 (01 / 06 особенный), et c.

Спасибо!

Ответы [ 2 ]

1 голос
/ 06 мая 2020

Вот идея с помощью базы R. Используйте cumsum для создания групп, когда день равен S, возьмите последовательность длины каждой и замените максимальное значение (которое соответствует S) на 0, т.е.

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

, что дает

   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
0 голосов
/ 06 мая 2020

Вот подход dplyr. Вы можете использовать cumsum, чтобы сгруппировать дни, предшествующие особому дню вместе, а затем обратный отсчет, взяв количество дней n() и вычтите номер строки row_number() в группе.

library(dplyr)

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

Выход

# 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
...