【问题标题】:Group column by regular interval [duplicate]按定期间隔对列进行分组[重复]
【发布时间】:2022-01-15 04:24:22
【问题描述】:

我正在努力解决一个看似简单的任务。在这种类型的数据中:

df <- data.frame(
  A = c(1,2,3,4,1,2,3,2,2,2,2,1,1,1,1,6,7)
)

我想添加一个id 变量,该变量将A 列按固定间隔分组,例如5。另一个困难是行数是 17,因此 不是 5 的倍数:

df <- data.frame(
  A = c(1,2,3,4,1,2,3,2,2,2,2,1,1,1,1,6,7),
  id = c("a","a","a","a","a", 
         "b","b","b","b","b",
         "c","c","c","c","c",
         "d","d"))

如何做到这一点?

【问题讨论】:

  • 你说你在挣扎——你试过什么?

标签: r


【解决方案1】:

基础 R

df$id <- rep(letters, each = 5, length = nrow(df))

dplyr

library(dplyr)
df %>% 
  mutate(id = rep(letters, each = 5, length = n()))

输出

df
   A id
1  1  a
2  2  a
3  3  a
4  4  a
5  1  a
6  2  b
7  3  b
8  2  b
9  2  b
10 2  b
11 2  c
12 1  c
13 1  c
14 1  c
15 1  c
16 6  d
17 7  d

【讨论】:

    【解决方案2】:
    df <- data.frame(A = c(1, 2, 3, 4, 1, 2, 3, 2, 2, 2, 2, 1, 1, 1, 1, 6, 7))
    
    library(dplyr)
    
    df %>% 
      mutate(grp = (row_number() - 1) %/% 5)
    #>    A grp
    #> 1  1   0
    #> 2  2   0
    #> 3  3   0
    #> 4  4   0
    #> 5  1   0
    #> 6  2   1
    #> 7  3   1
    #> 8  2   1
    #> 9  2   1
    #> 10 2   1
    #> 11 2   2
    #> 12 1   2
    #> 13 1   2
    #> 14 1   2
    #> 15 1   2
    #> 16 6   3
    #> 17 7   3
    

    reprex package (v2.0.1) 于 2022 年 1 月 14 日创建

    df %>% 
      mutate(grp = letters[(row_number() - 1) %/% 5 + 1])
    
       A grp
    1  1   a
    2  2   a
    3  3   a
    4  4   a
    5  1   a
    6  2   b
    7  3   b
    8  2   b
    9  2   b
    10 2   b
    11 2   c
    12 1   c
    13 1   c
    14 1   c
    15 1   c
    16 6   d
    17 7   d
    

    【讨论】:

    • 非常感谢。 %/%是什么意思?
    • %/% --> 整数除法的余数,@ChrisRuehlemann!例如,3 %% 2 等于 1。
    • %/% 返回除法的整数部分。这会导致所需的数字序列,c(0:16) 是 5 的倍数
    【解决方案3】:

    data.table 解决方案:

    library(data.table)
    
    setDT(df)[, grp := rep(letters, each = 5, length = .N)]
    

    输出

        A grp
     1: 1   a
     2: 2   a
     3: 3   a
     4: 4   a
     5: 1   a
     6: 2   b
     7: 3   b
     8: 2   b
     9: 2   b
    10: 2   b
    11: 2   c
    12: 1   c
    13: 1   c
    14: 1   c
    15: 1   c
    16: 6   d
    17: 7   d
    

    基准测试

    看起来base R是最快的:

    bm <- microbenchmark::microbenchmark(
      andrew.data.table = setDT(df)[, grp := rep(letters, each = 5, length = .N)],
      yuriy = df %>%
        mutate(grp = letters[(row_number() - 1) %/% 5 + 1]),
      paul = df %>%
        mutate(id = rep(letters, each=5)[1:n()]),
      Maël_baseR = df$id <- rep(letters, each = 5, length = nrow(df)),
      Maël_dplyr = df %>%
        mutate(id = rep(letters, each = 5, length = n())),
      times=1000L
    )
    
    autoplot(bm)
    

    【讨论】:

      【解决方案4】:

      一个可能的解决方案:

      library(dplyr)
      
      df <- data.frame(
        A = c(1,2,3,4,1,2,3,2,2,2,2,1,1,1,1,6,7)
      )
      
      df %>% 
        mutate(id = rep(letters, each=5)[1:n()])
      
      #>    A id
      #> 1  1  a
      #> 2  2  a
      #> 3  3  a
      #> 4  4  a
      #> 5  1  a
      #> 6  2  b
      #> 7  3  b
      #> 8  2  b
      #> 9  2  b
      #> 10 2  b
      #> 11 2  c
      #> 12 1  c
      #> 13 1  c
      #> 14 1  c
      #> 15 1  c
      #> 16 6  d
      #> 17 7  d
      

      【讨论】:

        猜你喜欢
        • 2019-04-10
        • 2011-03-01
        • 2019-01-30
        • 2021-04-29
        • 2016-06-13
        • 1970-01-01
        • 2021-02-25
        • 1970-01-01
        • 2021-07-07
        相关资源
        最近更新 更多