【问题标题】:Assign event number based on Date of occurece in R dataframe根据 R 数据框中的发生日期分配事件编号
【发布时间】:2021-03-22 02:59:11
【问题描述】:

如何根据满足以下条件的发生日期来分配事件编号。

  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

【问题讨论】:

    标签: r dataframe loops dplyr tidyverse


    【解决方案1】:

    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))))
    

    【讨论】:

      【解决方案2】:

      也许路很长,但可以完成任务:

      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 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-04
        • 2018-02-24
        • 2014-12-07
        • 1970-01-01
        • 1970-01-01
        • 2013-06-06
        • 1970-01-01
        • 2022-10-01
        相关资源
        最近更新 更多