Как указать количество событий, которые произошли до и после события

#r

#r

Вопрос:

Для любой заданной строки я хочу знать, на сколько x событий эта строка отличается от первого раза, когда y-событие произошло в моем наборе данных, либо до y-события ( — ), либо после y-события ( ).

Поскольку это относится к моему набору данных, x-события — это строки, где df $ type = «ES». y-событие — это первый раз, когда df$ type = «PH».

Я нашел решение, которое работает, в котором я использую case_when(), но я хотел бы знать, есть ли более элегантное решение.

 library(tidyverse)
# What I have 

df <- data.frame(
  type = c("ES", "OT", "ES", "PH", "ES", "PH", "OT", "ES"),
  bef_aft_PH = c(-3, -2, -1, 0, 1, 2, 3, 4),
  rownum_at_PH = c(4,4,4,4,4,4,4,4),
  date = as.POSIXct(c("2019/01/01", "2019/01/05", "2019/01/15", "2019/02/19", "2019/03/11", "2019/03/22", "2019/04/20", "2019/05/01"))
)

df
#>   type bef_aft_PH rownum_at_PH       date
#> 1   ES         -3            4 2019-01-01
#> 2   OT         -2            4 2019-01-05
#> 3   ES         -1            4 2019-01-15
#> 4   PH          0            4 2019-02-19
#> 5   ES          1            4 2019-03-11
#> 6   PH          2            4 2019-03-22
#> 7   OT          3            4 2019-04-20
#> 8   ES          4            4 2019-05-01


# Non-elegant Solution
df %>% 
  mutate(EScumsum = cumsum(type == "ES"),
         ES_bef_aft_PH = case_when(
           bef_aft_PH < 0 ~ as.double(x = EScumsum - (EScumsum[match("PH", .$type)]   1)), 
           bef_aft_PH == 0 ~ as.double(x = EScumsum - EScumsum),
           bef_aft_PH > 0 ~ as.double(x = EScumsum - EScumsum[match("PH", .$type)])
         ))
#>   type bef_aft_PH rownum_at_PH       date EScumsum ES_bef_aft_PH
#> 1   ES         -3            4 2019-01-01        1            -2
#> 2   OT         -2            4 2019-01-05        1            -2
#> 3   ES         -1            4 2019-01-15        2            -1
#> 4   PH          0            4 2019-02-19        2             0
#> 5   ES          1            4 2019-03-11        3             1
#> 6   PH          2            4 2019-03-22        3             1
#> 7   OT          3            4 2019-04-20        3             1
#> 8   ES          4            4 2019-05-01        4             2
  

Я не ожидал, что мне потребуется обернуть все аргументы RHS case_when в as.double(), поэтому мне интересно узнать, почему мне также нужно было это сделать.

Комментарии:

1. Непонятно. Можете ли вы объяснить, как первые две строки имеют ES_bef_aft_PH = -2 ?

Ответ №1:

 df %>%
  mutate(ES_PH1cumsum  = cumsum(type == "ES" | bef_aft_PH == 0)) %>%
  mutate(ES_bef_aft_PH = ES_PH1cumsum - ES_PH1cumsum[match(0, .$bef_aft_PH)])


  type bef_aft_PH rownum_at_PH       date ES_PH1cumsum ES_bef_aft_PH
1   ES         -3            4 2019-01-01            1            -2
2   OT         -2            4 2019-01-05            1            -2
3   ES         -1            4 2019-01-15            2            -1
4   PH          0            4 2019-02-19            3             0
5   ES          1            4 2019-03-11            4             1
6   PH          2            4 2019-03-22            4             1
7   OT          3            4 2019-04-20            4             1
8   ES          4            4 2019-05-01            5             2