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 中的行条件列操作的主要内容,如果未能解决你的问题,请参考以下文章