【问题标题】:data.table: subset by indexdata.table:索引子集
【发布时间】:2019-08-12 05:57:45
【问题描述】:

在下面的数据表中,我想选择具有唯一id 和列pos2 中最小值的行:

dt = data.table(id = c(1,2,2,3,3,3),
            pos1 = c(0.1, 0.2, 0.2, 0.3, 0.3, 0.3),
            pos2 = c(0.1, 0.25, 0.21, 0.34, 0.31, 0.32))

   id pos1 pos2
1:  1  0.1 0.10
2:  2  0.2 0.25
3:  2  0.2 0.21
4:  3  0.3 0.34
5:  3  0.3 0.31
6:  3  0.3 0.32

我现在的做法是创建一个中间表:

dt.red = dt[, .(pos2 = first(sort(pos2))), by = id]

   id pos2
1:  1 0.10
2:  2 0.21
3:  3 0.31

然后我合并得到想要的最终结果

merge(dt, dt.red)

   id pos2 pos1
1:  1 0.10  0.1
2:  2 0.21  0.2
3:  3 0.31  0.3

有没有更简洁的方法可以使用 data.table 实现这一目标?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    我们可以使用.I 获取行索引,并使用i 中的行索引来对行进行子集化

    dt[dt[order(pos2), .I[1], by = id]$V1]
    #   id pos1 pos2
    #1:  1  0.1 0.10
    #2:  2  0.2 0.21
    #3:  3  0.3 0.31
    

    setorder

    setorder(dt, id, pos2)[, .SD[1L], id]
    

    【讨论】:

      【解决方案2】:

      没有.I也可以这样做,但会慢一些*

      dt[order(pos2), head(.SD, 1), id]
      #    id pos1 pos2
      # 1:  1  0.1 0.10
      # 2:  2  0.2 0.21
      # 3:  3  0.3 0.31
      

      *也许不是,见下面的cmets

      【讨论】:

      • 它可能不会慢很多。无论如何,它内置了优化,dt[order(pos2), head(.SD, 1), by=id, verbose=TRUE] 可见
      • 是的,也许我在这里的描述太强了。我基于this question 中的基准进行了该声明。随心所欲地制定该基准,它有点不同,因为没有order(),并且无论如何测试数据可能太小而无法得出任何结论。
      • 好的。 head(.SD, 1) 已针对 GForce 优化了一段时间,但仅适用于 n=1。 github.com/Rdatatable/data.table/pull/3463 最近可能已经扩展了它,但我不确定。
      • 好的,我明白了。该基准没有反映在这种情况下将使用的优化,因为它只测试n > 1
      • @Frank 不,还没有。此 PR 处理缺少的 n 以填充 6L,这以前是错误的,但仍然会禁用 gforce
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 2013-01-08
      • 2016-04-20
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多