【问题标题】:Generate sequence within sub group in data.table在 data.table 的子组内生成序列
【发布时间】:2020-03-25 07:57:32
【问题描述】:

我想在子组列中生成序列,例如我有两列 id1,val,想按 id1,val 对数据进行排序,然后为 id1 生成计数器。

输入

input <- data.frame("id1"=c(1,1,1,1,2,2,2),val=c(2,3,4,1,4,3,5))

预期输出

id1,val,grp 
1,1,1
1,2,2
1,3,3
1,4,4
2,3,1
2,4,2
2,5,3

以前的参考帖子

Count for sub group using .grp in data.table

Numbering rows within groups in a data frame

在代码下方使用(我正在尝试在大数据上使用代码并寻找解决方案,因此我不需要在生成序列之前添加额外的步骤来对“val”列的数据进行排序)

input[, new1:=seq_len(.N), by=c('id1')]

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    我们按“id1”、sort“val”分组,然后将“grp”创建为row_number()

    input %>%
      group_by(id1) %>%
      mutate(val = sort(val), grp= row_number())
    

    或者另一种选择是arrange

    input %>%
       arrange(id1, val) %>%
       group_by(id1) %>%
       mutate(grp = row_number())
    

    或使用data.table

    library(data.table)
    setDT(input)[, c("grp", "val") := .(seq_len(.N), sort(val)), by = id1]
    input
    #   id1 val grp
    #1:   1   1   1
    #2:   1   2   2
    #3:   1   3   3
    #4:   1   4   4
    #5:   2   3   1
    #6:   2   4   2
    #7:   2   5   3
    

    如果我们也需要排序,使用setorder基于'id1'和'val'来排序,然后创建'grp'作为'id1'的rowid

    input <- data.frame("id1"=c(1,1,1,1,2,2,2),val=c(2,3,4,1,4,3,5), 
            achar=c('a','a','b','b','d','c','e'))
    setorder(setDT(input), id1, val)[, grp := rowid(id1)][]
    #   id1 val achar grp
    #1:   1   1     b   1
    #2:   1   2     a   2
    #3:   1   3     a   3
    #4:   1   4     b   4
    #5:   2   3     c   1
    #6:   2   4     d   2
    #7:   2   5     e   3
    

    【讨论】:

    • 上述解决方案完美运行,但如果 data.table 中有额外的列,则无法正确调整。
    • @R007 setDT(input)[, c("grp", "val") := .(seq_len(.N), sort(val)), by = id1] 即使有其他列或 dplyr 解决方案,这也可以工作。我不明白这个问题
    • 我在新的 data.table 上应用了逻辑,并且 achar 的值不正确。例如输入
    • 当数据为“val”排序时,它应该在行级别对数据进行排序。 achar 应该在 (b,a,a,b,c,d,e)
    【解决方案2】:

    这里有一点factor hack。

    # Load library
    library(data.table)
    
    # Create data table
    input <- data.table(id1=c(1,1,1,1,2,2,2),val=c(2,3,4,1,4,3,5))
    
    input[, foo := as.integer(factor(val)), by = "id1"]
    
    # Print result
    input
    #>    id1 val foo
    #> 1:   1   2   2
    #> 2:   1   3   3
    #> 3:   1   4   4
    #> 4:   1   1   1
    #> 5:   2   4   2
    #> 6:   2   3   1
    #> 7:   2   5   3
    
    # Reorder for comparison with question
    input[order(id1, val)]
    #>    id1 val foo
    #> 1:   1   1   1
    #> 2:   1   2   2
    #> 3:   1   3   3
    #> 4:   1   4   4
    #> 5:   2   3   1
    #> 6:   2   4   2
    #> 7:   2   5   3
    

    reprex package (v0.3.0) 于 2019 年 11 月 29 日创建

    【讨论】:

      猜你喜欢
      • 2013-09-19
      • 2013-09-16
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 2013-11-21
      • 2016-04-02
      相关资源
      最近更新 更多