【问题标题】:assign variable based on starting/ending pattern根据开始/结束模式分配变量
【发布时间】:2018-12-20 03:06:46
【问题描述】:

我有这个数据集:

a <- data.frame("session_id" = c(rep(1,10), rep(2,7), rep(3,2)),
                "content" = c("A", "B", "C","open", "A", "J", "M", "K","exit", "D", 
                "open", "U", "T","quit", "I", "M" , "A", "Q", "M" ), 
            "type" = c("non-edit", "non-edit", "non-edit", "edit", "edit", "edit", 
            "edit", "edit", "edit", "non-edit", "edit", "edit", "edit", 
            "edit", "non-edit", "non-edit", "non-edit", "non-edit", "non-edit"))

我希望根据内容列将类型列分配给“非编辑”或“编辑”类型。当我们在内容中检测到“打开”直到“退出”或“退出”时,类型将是“编辑”。您可以在我提供的示例中看到该示例。

【问题讨论】:

    标签: r dataframe dplyr grouping data-manipulation


    【解决方案1】:

    这是使用cumsum 在基础 R 中的一种方法:

    a$new_type <- c("non-edit","edit")[
      cumsum(a$content=="open") - c(0,head(cumsum(a$content %in% c("exit","quit")),-1)) +1]
    #    session_id content     type new_type
    # 1           1       A non-edit non-edit
    # 2           1       B non-edit non-edit
    # 3           1       C non-edit non-edit
    # 4           1    open     edit     edit
    # 5           1       A     edit     edit
    # 6           1       J     edit     edit
    # 7           1       M     edit     edit
    # 8           1       K     edit     edit
    # 9           1    exit     edit     edit
    # 10          1       D non-edit non-edit
    # 11          2    open     edit     edit
    # 12          2       U     edit     edit
    # 13          2       T     edit     edit
    # 14          2    quit     edit     edit
    # 15          2       I non-edit non-edit
    # 16          2       M non-edit non-edit
    # 17          2       A non-edit non-edit
    # 18          3       Q non-edit non-edit
    # 19          3       M non-edit non-edit
    

    【讨论】:

      【解决方案2】:

      计划:逐行查找内容列中的“转换键”。如果键是“打开”,则立即行动,如果“退出”或“退出”则在下一行行动。 考虑以下代码来实现:

      last  <-  'exit'  #initialize last
      keys <- c('open','exit','quit')  #transition keys
      for (i in 1:nrow(a)) {
      a$type[i]  <-  ifelse(a$content[i] %in% keys, 'edit', 
      ifelse(last=='open','edit','non-edit'))
      last  <- ifelse(a$content[i]%in% keys, a$content[i],last)
      }
      a
      R> a
         session_id content     type
      1           1       A non-edit
      2           1       B non-edit
      3           1       C non-edit
      4           1    open     edit
      5           1       A     edit
      6           1       J     edit
      7           1       M     edit
      8           1       K     edit
      9           1    exit     edit
      10          1       D non-edit
      11          2    open     edit
      12          2       U     edit
      13          2       T     edit
      14          2    quit     edit
      15          2       I non-edit
      16          2       M non-edit
      17          2       A non-edit
      18          3       Q non-edit
      19          3       M non-edit
      

      【讨论】:

        【解决方案3】:

        这是一个不需要分组的管道。

        library(dplyr)
        library(tidyr)
        
        b <- 
            a %>% 
            # 1. Mark the boundaries of the 'edit' regions.
            mutate(type = case_when(content == "open"           ~ "edit", 
                                    grepl("exit|quit", content) ~ "non-edit",
                                                           TRUE ~ NA_character_)) %>%
            # 2. Fill the NAs with the last good value. 'open' down to 'exit/quit'
            #    will be filled with 'edit'.
            tidyr::fill(type) %>%
            # 3. Replace unfilled NAs, like at the top of the table.
            replace_na(list(type = "non-edit")) %>%
            # 4. Rename the exit/quit boundary.
            mutate(type = ifelse(grepl("exit|quit", content), "edit", type))
        
        b
        
        #>    session_id content     type
        #> 1           1       A non-edit
        #> 2           1       B non-edit
        #> 3           1       C non-edit
        #> 4           1    open     edit
        #> 5           1       A     edit
        #> 6           1       J     edit
        #> 7           1       M     edit
        #> 8           1       K     edit
        #> 9           1    exit     edit
        #> 10          1       D non-edit
        #> 11          2    open     edit
        #> 12          2       U     edit
        #> 13          2       T     edit
        #> 14          2    quit     edit
        #> 15          2       I non-edit
        #> 16          2       M non-edit
        #> 17          2       A non-edit
        #> 18          3       Q non-edit
        #> 19          3       M non-edit
        

        【讨论】:

          【解决方案4】:

          我们创建一个新列 (new_type) 并将值初始化为“非编辑”。然后我们找到出现“open”和“quit”的索引,并使用mapply在它们之间创建一个索引序列,并将相应的值替换为“edit”

          a$new_type <- "non-edit"
          open_ind <- which(a$content == "open")
          close_ind <- which(a$content %in% c("quit", "exit"))
          a$new_type[unlist(mapply(":", open_ind, close_ind))] <- "edit"
          
          
          a
          #   session_id content     type new_type
          #1           1       A non-edit non-edit
          #2           1       B non-edit non-edit
          #3           1       C non-edit non-edit
          #4           1    open     edit     edit
          #5           1       A     edit     edit
          #6           1       J     edit     edit
          #7           1       M     edit     edit
          #8           1       K     edit     edit
          #9           1    exit     edit     edit
          #10          1       D non-edit non-edit
          #11          2    open     edit     edit
          #12          2       U     edit     edit
          #13          2       T     edit     edit
          #14          2    quit     edit     edit
          #15          2       I non-edit non-edit
          #16          2       M non-edit non-edit
          #17          2       A non-edit non-edit
          #18          3       Q non-edit non-edit
          #19          3       M non-edit non-edit
          

          要了解步骤,

          open_ind
          #[1]  4 11
          close_ind
          #[1]  9 14
          unlist(mapply(":", open_ind, close_ind))
          #[1]  4  5  6  7  8  9 11 12 13 14
          

          【讨论】:

            【解决方案5】:

            在按 'session_id' 分组后,通过获取逻辑表达式的累积和来创建另一个组,并将其用于分配值 'edit' 和 'non-edit'

            library(dplyr)
            a %>% 
              group_by(session_id) %>% 
              group_by(grp = cumsum((content == "open")|
                 lag(content %in% c("exit", "quit"), 
                          default = first(content))), add = TRUE) %>%
              mutate(type1 = case_when(any(content %in% c("open", "exit", "quit")) ~ "edit", 
                                     TRUE ~ "non-edit")) %>%
              ungroup %>%
              select(-grp)
            # A tibble: 19 x 4
            #   session_id content type     type1   
            #        <dbl> <fct>   <fct>    <chr>   
            # 1          1 A       non-edit non-edit
            # 2          1 B       non-edit non-edit
            # 3          1 C       non-edit non-edit
            # 4          1 open    edit     edit    
            # 5          1 A       edit     edit    
            # 6          1 J       edit     edit    
            # 7          1 M       edit     edit    
            # 8          1 K       edit     edit    
            # 9          1 exit    edit     edit    
            #10          1 D       non-edit non-edit
            #11          2 open    edit     edit    
            #12          2 U       edit     edit    
            #13          2 T       edit     edit    
            #14          2 quit    edit     edit    
            #15          2 I       non-edit non-edit
            #16          2 M       non-edit non-edit
            #17          2 A       non-edit non-edit
            #18          3 Q       non-edit non-edit
            #19          3 M       non-edit non-edit
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2018-04-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-25
              • 2018-05-22
              相关资源
              最近更新 更多