【问题标题】:Group_by id and count the consective NA's and then restart counting when a new series of NA's is encounteredGroup_by id 并计算连续的 A,然后在遇到新的一系列 NA 时开始计数
【发布时间】:2022-01-17 20:04:52
【问题描述】:

我有一个这样的数据框:

df <- data_frame(id = c(rep('A', 10), rep('B', 10)),
                 value = c(1:3, rep(NA, 2), 1:2, rep(NA, 3), 1, rep(NA, 4), 1:3, rep(NA, 2)))

我需要计算value 列中连续 NA 的数量。计数需要按 ID 分组,每次遇到新的 NA 或新的一系列 NA 时都需要从 1 重新开始。预期的输出应如下所示:

df$expected_output <- c(rep(NA, 3), 1:2, rep(NA, 2), 1:3, NA, 1:4, rep(NA, 3), 1:2)

如果有人能给我一个 dplyr 解决方案,那就太好了:)

我尝试了一些方法,但都没有给出任何有意义的结果。提前谢谢^!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    使用dplyrdata.table 的解决方案。

    library(dplyr)
    library(data.table)
    
    df2 <- df %>%
      group_by(id) %>%
      mutate(info = rleid(value)) %>%
      group_by(id, info) %>%
      mutate(expected_output = row_number()) %>%
      ungroup() %>%
      mutate(expected_output = ifelse(!is.na(value), NA, expected_output)) %>%
      select(-info)
    df2
    # # A tibble: 20 x 3  
    #     id    value expected_output
    #     <chr> <dbl>           <int>
    #  1 A         1              NA
    #  2 A         2              NA
    #  3 A         3              NA
    #  4 A        NA               1
    #  5 A        NA               2
    #  6 A         1              NA
    #  7 A         2              NA
    #  8 A        NA               1
    #  9 A        NA               2
    # 10 A        NA               3
    # 11 B         1              NA
    # 12 B        NA               1
    # 13 B        NA               2
    # 14 B        NA               3
    # 15 B        NA               4
    # 16 B         1              NA
    # 17 B         2              NA
    # 18 B         3              NA
    # 19 B        NA               1
    # 20 B        NA               2
    

    【讨论】:

    • 嘿,非常感谢,但不幸的是,它不会在遇到新的 NA 时重置回一个,正如我在问题中的“expected_output 列所做的那样。谢谢
    • @stevezissou 对不起。请查看我的更新答案。
    • 谢谢!看起来很棒!
    【解决方案2】:

    我们可以使用rle 来获取是或不是na 的组的长度,如果它们是seq,我们可以使用purrr::map2 来应用NA 并获得不断增长的计数,或者只需填写@ 987654326@ 值使用rep

    library(tidyverse)
    
    count_na <- function(x) {
      r <- rle(is.na(x))
      consec <- map2(r$lengths, r$values, ~ if (.y) seq(.x) else rep(NA, .x))
      unlist(consec)
    }
    
    df %>%
      mutate(expected_output = count_na(value))
    #> # A tibble: 20 × 3
    #>    id    value expected_output
    #>    <chr> <dbl>           <int>
    #>  1 A         1              NA
    #>  2 A         2              NA
    #>  3 A         3              NA
    #>  4 A        NA               1
    #>  5 A        NA               2
    #>  6 A         1              NA
    #>  7 A         2              NA
    #>  8 A        NA               1
    #>  9 A        NA               2
    #> 10 A        NA               3
    #> 11 B         1              NA
    #> 12 B        NA               1
    #> 13 B        NA               2
    #> 14 B        NA               3
    #> 15 B        NA               4
    #> 16 B         1              NA
    #> 17 B         2              NA
    #> 18 B         3              NA
    #> 19 B        NA               1
    #> 20 B        NA               2
    

    【讨论】:

      【解决方案3】:

      这是使用rle的解决方案:

      x <- rle(is.na(df$value))
      df$new[is.na(df$value)] <- sequence(x$lengths[x$values])
      
      # A tibble: 20 x 3
         id    value   new
         <chr> <dbl> <int>
       1 A         1    NA
       2 A         2    NA
       3 A         3    NA
       4 A        NA     1
       5 A        NA     2
       6 A         1    NA
       7 A         2    NA
       8 A        NA     1
       9 A        NA     2
      10 A        NA     3
      11 B         1    NA
      12 B        NA     1
      13 B        NA     2
      14 B        NA     3
      15 B        NA     4
      16 B         1    NA
      17 B         2    NA
      18 B         3    NA
      19 B        NA     1
      20 B        NA     2
      

      【讨论】:

        【解决方案4】:

        另一个解决方案:

        library(tidyverse)
        
        df %>% 
          mutate(aux =data.table::rleid(value)) %>% 
          group_by(id, aux) %>% 
          mutate(eout = ifelse(is.na(value), row_number(), NA_real_)) %>%
          ungroup %>% select(-aux)
        
        #> # A tibble: 20 × 4
        #>    id    value expected_output  eout
        #>    <chr> <dbl>           <int> <dbl>
        #>  1 A         1              NA    NA
        #>  2 A         2              NA    NA
        #>  3 A         3              NA    NA
        #>  4 A        NA               1     1
        #>  5 A        NA               2     2
        #>  6 A         1              NA    NA
        #>  7 A         2              NA    NA
        #>  8 A        NA               1     1
        #>  9 A        NA               2     2
        #> 10 A        NA               3     3
        #> 11 B         1              NA    NA
        #> 12 B        NA               1     1
        #> 13 B        NA               2     2
        #> 14 B        NA               3     3
        #> 15 B        NA               4     4
        #> 16 B         1              NA    NA
        #> 17 B         2              NA    NA
        #> 18 B         3              NA    NA
        #> 19 B        NA               1     1
        #> 20 B        NA               2     2
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-01-11
          • 1970-01-01
          • 2016-11-25
          • 2014-12-03
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多