Присвоить номер события на основе даты возникновения в R dataframe

#r #dataframe #loops #dplyr #tidyverse

#r #dataframe #циклы #dplyr #tidyverse

Вопрос:

Как присвоить номер события на основе их даты возникновения, удовлетворяющей следующим условиям.

  1. Если событие происходит не менее 3 дней подряд (или более), присвоить номер события e1 и т. Д. И мутировать (присоединяться) к исходному фрейму данных.
  2. Если вхождение происходит не в течение непрерывных 3 дней, назначьте NA и измените исходный фрейм данных. Во временных рядах dts , как я могу этого достичь. Фрейм выходных данных будет выглядеть dts_output следующим образом (выполняется вручную).
 
    dts<-structure(list(Date = structure(c(16442, 16443, 16444, 16445, 
     16484, 16485, 16486, 16487, 16488, 16489, 16490, 16491, 16492, 
    16493, 16499, 16500, 16511, 16512, 16513), class = "Date"), cct = c(11, 
     11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 
     11, 11)), row.names = c(NA, -19L), class = c("tbl_df", "tbl", 
     "data.frame"))

    dts

#Expected output

    dts_output<-structure(list(Date = structure(c(16442, 16443, 16444, 16445, 
           16484, 16485, 16486, 16487, 16488, 16489, 16490, 16491, 16492, 
           16493, 16499, 16500, 16511, 16512, 16513), class = "Date"), cct = c(11, 
           11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 
           11, 11), event = c("e1", "e1", "e1", "e1", "e2", "e2", "e2", 
           "e2", "e2", "e2", "e2", "e2", "e2", "e2", NA, NA, "e3", "e3", 
           "e3")), row.names = c(NA, -19L), spec = structure(list(cols = list(
           Date = structure(list(), class = c("collector_character", 
           "collector")), cct = structure(list(), class = c("collector_double", 
           "collector")), event = structure(list(), class = c("collector_character", 
           "collector"))), default = structure(list(), class = c("collector_guess", 
           "collector")), skip = 1L), class = "col_spec"), class = c("spec_tbl_df", 
           "tbl_df", "tbl", "data.frame"))
    dts_output
 

Ответ №1:

Может быть, длинный путь, но может выполнить задачу:

 library(dplyr)
library(tidyr)
#Code
dts$Var <- c(0,diff(dts$Date))
i <- which(dts$Var!=1)
dts$Var <- ifelse(dts$Var==1,NA,dts$Var)
dts$Var[i] <- 1:length(i)
#Fill
input1 <- dts %>% fill(Var) %>%
  group_by(Var) %>%
  mutate(Var2=ifelse(n()>=3,cur_group_id(),NA))
#Extract unique
add <- data.frame(Var2=unique(na.omit(input1$Var2)),stringsAsFactors = F)
add$Group <- paste0('e',1:nrow(add))
#Merge
input2 <- input1 %>% left_join(add) %>%
  select(-c(Var,Var2))
 

Вывод:

 # A tibble: 19 x 4
# Groups:   Var [4]
     Var Date         cct Group
   <dbl> <date>     <dbl> <chr>
 1     1 2015-01-07    11 e1   
 2     1 2015-01-08    11 e1   
 3     1 2015-01-09    11 e1   
 4     1 2015-01-10    11 e1   
 5     2 2015-02-18    11 e2   
 6     2 2015-02-19    11 e2   
 7     2 2015-02-20    11 e2   
 8     2 2015-02-21    11 e2   
 9     2 2015-02-22    11 e2   
10     2 2015-02-23    11 e2   
11     2 2015-02-24    11 e2   
12     2 2015-02-25    11 e2   
13     2 2015-02-26    11 e2   
14     2 2015-02-27    11 e2   
15     3 2015-03-05    11 NA   
16     3 2015-03-06    11 NA   
17     4 2015-03-17    11 e3   
18     4 2015-03-18    11 e3   
19     4 2015-03-19    11 e3 
 

Ответ №2:

Опция с data.table

 library(data.table)
setDT(dts)[, grp :=cumsum(c(TRUE, diff(Date) != 1)), .(cct)]
i1 <- dts[, .I[.N >= 3], .(cct, grp)]$V1
dts[i1,  event := paste0('e', .GRP), .(cct, grp)][, grp := NULL][]
 

-вывод

 #         Date cct event
# 1: 2015-01-07  11    e1
# 2: 2015-01-08  11    e1
# 3: 2015-01-09  11    e1
# 4: 2015-01-10  11    e1
# 5: 2015-02-18  11    e2
# 6: 2015-02-19  11    e2
# 7: 2015-02-20  11    e2
# 8: 2015-02-21  11    e2
# 9: 2015-02-22  11    e2
#10: 2015-02-23  11    e2
#11: 2015-02-24  11    e2
#12: 2015-02-25  11    e2
#13: 2015-02-26  11    e2
#14: 2015-02-27  11    e2
#15: 2015-03-05  11  <NA>
#16: 2015-03-06  11  <NA>
#17: 2015-03-17  11    e3
#18: 2015-03-18  11    e3
#19: 2015-03-19  11    e3
 

Или с помощью tidyverse

 library(dplyr)
library(stringr)
dts %>%
     group_by(cct) %>%
     group_by(grp = cumsum(c(TRUE, diff(Date) != 1)), .add = TRUE) %>%
     filter(n() >=3) %>%
     mutate(event = str_c('e', cur_group_id())) %>%
     ungroup %>% 
     select(-grp) %>% 
     left_join(dts %>% 
                 mutate(rn = row_number()), .) %>%
     select(-rn)
# A tibble: 19 x 3
#   Date         cct event
#   <date>     <dbl> <chr>
# 1 2015-01-07    11 e1   
# 2 2015-01-08    11 e1   
# 3 2015-01-09    11 e1   
# 4 2015-01-10    11 e1   
# 5 2015-02-18    11 e2   
# 6 2015-02-19    11 e2   
# 7 2015-02-20    11 e2   
# 8 2015-02-21    11 e2   
# 9 2015-02-22    11 e2   
#10 2015-02-23    11 e2   
#11 2015-02-24    11 e2   
#12 2015-02-25    11 e2   
#13 2015-02-26    11 e2   
#14 2015-02-27    11 e2   
#15 2015-03-05    11 <NA> 
#16 2015-03-06    11 <NA> 
#17 2015-03-17    11 e3   
#18 2015-03-18    11 e3   
#19 2015-03-19    11 e3   
 

Или это можно упростить до

 dts %>%
  group_by(cct) %>%
  group_by(grp = cumsum(c(TRUE, diff(Date) != 1)), .add = TRUE) %>% 
  mutate(event = if(n() >=3) cur_group_id()[n() >=3] else NA ) %>% 
  ungroup %>% 
  mutate(event = str_c('e', as.integer(factor(event))))