【问题标题】:Is there a way to group values in a column between data gaps in R?有没有办法在 R 中的数据间隙之间对列中的值进行分组?
【发布时间】:2021-10-26 06:56:28
【问题描述】:

当数据是连续的时,我想将我的数据分组到不同的块中。尝试从这样的虚拟数据中获取组列:

       a     b group
   <dbl> <dbl> <dbl>
 1     1     1     1
 2     2     2     1
 3     3     3     1
 4     4    NA    NA
 5     5    NA    NA
 6     6    NA    NA
 7     7    12     2
 8     8    15     2
 9     9    NA    NA
10    10    25     3

我尝试过使用

test %>% mutate(test = complete.cases(.)) %>%
  group_by(group = cumsum(test == TRUE)) %>%
  select(group, everything())

但它并没有按预期工作:

   group     a     b test 
   <int> <dbl> <dbl> <lgl>
 1     1     1     1 TRUE 
 2     2     2     2 TRUE 
 3     3     3     3 TRUE 
 4     3     4    NA FALSE
 5     3     5    NA FALSE
 6     3     6    NA FALSE
 7     4     7    12 TRUE 
 8     5     8    15 TRUE 
 9     5     9    NA FALSE
10     6    10    25 TRUE 

有什么建议吗?

【问题讨论】:

标签: r


【解决方案1】:

在基础 R 中使用 rle -

transform(df, group1 = with(rle(!is.na(b)), rep(cumsum(values), lengths))) |>
  transform(group1 = replace(group1, is.na(b), NA))

#    a  b group group1
#1   1  1     1      1
#2   2  2     1      1
#3   3  3     1      1
#4   4 NA    NA     NA
#5   5 NA    NA     NA
#6   6 NA    NA     NA
#7   7 12     2      2
#8   8 15     2      2
#9   9 NA    NA     NA
#10 10 25     3      3 

【讨论】:

    【解决方案2】:

    如果您希望为此使用dplyr,可以考虑几种方法。

    首先,您可以查看从非完整案例(使用lag)到完整案例的转换。

    library(dplyr)
    
    test %>% 
      mutate(test = complete.cases(.)) %>%
      group_by(group = cumsum(test & !lag(test, default = F))) %>%
      mutate(group = replace(group, !test, NA))
    

    或者,您可以在 data.frame 中添加行号。然后,您可以过滤以仅包含完整的案例,并 group_by 根据行号的间隙使用 cumsum 进行枚举。然后,连接回原始数据。

    test$rn <- seq.int(nrow(test))
    
    test %>% 
      filter(complete.cases(.)) %>%
      group_by(group = c(0, cumsum(diff(rn) > 1)) + 1) %>%
      right_join(test) %>%
      arrange(rn) %>%
      dplyr::select(-rn)
    

    输出

           a     b group
       <int> <int> <dbl>
     1     1     1     1
     2     2     2     1
     3     3     3     1
     4     4    NA    NA
     5     5    NA    NA
     6     6    NA    NA
     7     7    12     2
     8     8    15     2
     9     9    NA    NA
    10    10    25     3
    

    【讨论】:

      【解决方案3】:

      使用 data.table,获取 rleid 然后删除 NAs 的组 ID,然后使用 factor 将序列固定为 integer 转换:

      library(data.table)
      
      setDT(test)[, group1 := {
        x <- complete.cases(test)
        grp <- rleid(x)
        grp[ !x ] <- NA
        as.integer(factor(grp))
        }]
      #      a  b group group1
      #  1:  1  1     1      1
      #  2:  2  2     1      1
      #  3:  3  3     1      1
      #  4:  4 NA    NA     NA
      #  5:  5 NA    NA     NA
      #  6:  6 NA    NA     NA
      #  7:  7 12     2      2
      #  8:  8 15     2      2
      #  9:  9 NA    NA     NA
      # 10: 10 25     3      3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-14
        • 1970-01-01
        • 2021-10-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多