【问题标题】:Subset a data.table given the row index for each group给定每个组的行索引,对 data.table 进行子集
【发布时间】:2016-07-03 10:57:09
【问题描述】:

这似乎是一个微不足道的问题,我似乎无法找到解决方案:

考虑两个data.tables

library(data.table)
dt <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

dt1 <- data.table(id = c(1,2),
                  V1 = c(2,1))

我如何对dt 进行子集化,其中dt1 告诉我分组id 的行号(V1) 我需要子集化?

例如,这里的结果将是

#    id val
# 1:  1  20
# 2:  2  10

更新

对建议的解决方案进行快速基准测试

library(data.table)
s <- 100000
set.seed(123)
dt <- data.table(id = rep(seq(1:s), each=10),
                 val = rnorm(n = s*10, 0, 1))

dt1 <- data.table(id = seq(1:s),
                  V1 = sample(1:10, s, replace=T))


library(microbenchmark)

microbenchmark(

  akrun = { dt[dt1, on='id'][, .SD[1:.N==V1] ,id] },

  david = { dt[dt1, val[i.V1], on = 'id', by = .EACHI] },

  symbolix = { dt[, id_seq := seq(1:.N), by=id][dt1, on=c(id_seq = "V1", "id") , nomatch=0] },

   times = 5

 )
#Unit: milliseconds
#     expr         min          lq        mean      median          uq         max neval
#    akrun 17809.51370 17887.89037 18005.32357 18043.80279 18130.78978 18154.62118     5
#    david    48.17367    53.76436    53.79004    54.69096    55.59657    56.72467     5
 #symbolix   507.67312   511.23492   562.59743   571.31160   579.61228   643.15525     5

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    另一种选择是使用by = .EACHI 以便在加入时对val 进行子集化

    dt[dt1, val[i.V1], on = 'id', by = .EACHI]
    #    id V1
    # 1:  1 20
    # 2:  2 10
    

    如果那里有更多列,则可以改用.SD[i.V1]


    附带说明一下,在 data.table v >= 1.9.8 中,.SD[val] 操作计划完全优化以使用 GForce- 所以请抓紧。

    【讨论】:

    • 那么.SD 是否已经在 1.9.7 中进行了优化?我很困惑。
    • @docendodiscimus 它针对显式使用正整数(例如.SD[2L])的情况进行了优化,但如果您将其作为变量传递(如val &lt;- 2L ; .SD[val])则不会进行优化。这应该在 v 1.9.8 中修复(希望如此)。
    • 非常好。我正在为.EACHI 解决方案而苦苦挣扎,所以我很高兴看到这个!
    【解决方案2】:

    一种选择是 join on 'id' 然后做子集

    dt[dt1, on='id'][, .SD[1:.N==V1] ,id][,V1:=NULL][]
    #   id val
    #1:  1  20
    #2:  2  10
    

    【讨论】:

    • 在类似的主题上,也许dt[, id_seq := seq(1:.N), by=id][dt1, on=c(id_seq = "V1", "id") , nomatch=0] (以避免.SD 分配)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 2017-12-23
    • 2019-03-31
    • 2012-09-06
    • 2020-07-24
    • 2021-07-23
    相关资源
    最近更新 更多