data.table 中的行条件列操作

Posted

技术标签:

【中文标题】data.table 中的行条件列操作【英文标题】:Row conditional column operations in data.table 【发布时间】:2018-01-04 09:35:04 【问题描述】:

我有一个大型 data.table,我需要根据完整 data.table 的一部分对每一行进行计算。作为一个例子,考虑下面的data.table,并假设每一行的I想要计算每行的num变量的总和,其中id2与当前行的id1匹配,并且时间变量在距离1以内当前行。

set.seed(123)

dat <- data.table(cbind(id1=sample(1:5,10,replace=T),
                        id2=sample(1:5,10,replace=T),
                        num=sample(1:10,10,replace=T),
                        time=sample(1:10,10,replace=T)))

这可以通过像这样遍历每一行来轻松完成

dat[,val:= 0]
for (i in 1:nrow(dat))
  this.val <- dat[ (id2==id1[i]) & (time>=time[i]-2) & (time<=time[i]+2),sum(num)]
  dat[i,val:=this.val]


dat

生成的 data.table 如下所示:

   > dat
        id1 id2 num time val
     1:   2   5   9   10   6
     2:   4   3   7   10   0
     3:   3   4   7    7  10
     4:   5   3  10    8   9
     5:   5   1   7    1   2
     6:   1   5   8    5   6
     7:   3   2   6    8  17
     8:   5   1   6    3  10
     9:   3   2   3    4   0
    10:   3   5   2    3   0

使用 data.table 执行此类操作的正确/快速方法是什么?

【问题讨论】:

【参考方案1】:

我们可以在这里通过创建'timeminus2'和'timeplus2'列来使用自连接,通过'id2'和'id1'和非等逻辑条件连接on以获得'的sum num' 并将 (:=) 'val' 列分配给原始数据集

tmp <- dat[.(id1 = id1, timeminus2 = time - 2, timeplus2 = time + 2), 
             .(val = sum(num)),
             on = .(id2 = id1, time >= timeminus2, time <= timeplus2),
             by = .EACHI
         ][is.na(val), val := 0][]
dat[, val := tmp$val][]
#     id1 id2 num time val
# 1:   2   5   9   10   6
# 2:   4   3   7   10   0
# 3:   3   4   7    7  10
# 4:   5   3  10    8   9
# 5:   5   1   7    1   2
# 6:   1   5   8    5   6
# 7:   3   2   6    8  17
# 8:   5   1   6    3  10
# 9:   3   2   3    4   0
#10:   3   5   2    3   0

【讨论】:

谢谢,这使我的代码快了 100 倍以上 :-) 只是出于好奇:是否有可能在 tmp 中包含其他变量,这样就可以避免写回原始数据集? @Mark 就像我创建了.(id1, ...),你可以把这些变量放在里面。

以上是关于data.table 中的行条件列操作的主要内容,如果未能解决你的问题,请参考以下文章

如何根据pyspark中的行和列条件过滤多行

R:根据来自另一个data.table的条件“标记”一行

根据列中的条件对数据框中的行进行子集/过滤

根据“如果单元格中的字符串”条件删除熊猫列中的行

根据谷歌电子表格中的行和列条件计算值

根据条件对 BigQuery 中的行进行重复数据删除