我想在我的data.table中添加一个新列.此列应包含满足特定条件的所有行的另一列的总和.一个例子:我的data.table如下所示:
require(data.table) DT <- data.table(n=c("a","a","b","b"),t=c(10,20,33,40,50,22,25,34,11),v=c(20,15,16,17,11,12,10) ) DT n t v 1: a 10 20 2: a 20 15 3: a 33 16 4: a 40 17 5: a 50 11 6: a 22 12 7: b 25 20 8: b 34 22 9: b 11 10
对于每行x和每行i,其中abs(t [i] -t [x])= 10,我想计算
foo = sum( v[i] * abs(t[i] - t[x]) )
在sql中,我将使用自联接来解决这个问题.在R中,我可以使用for循环:
for (i in 1:nrow(DT)) DT[i,foo:=DT[n==DT[i]$n & abs(t-DT[i]$t)<=10,sum(v * abs(t-DT[i]$t) )]] DT n t v foo 1: a 10 20 150 2: a 20 15 224 3: a 33 16 119 4: a 40 17 222 5: a 50 11 170 6: a 22 12 30 7: b 25 20 198 8: b 34 22 180 9: b 11 10 0
不幸的是,我必须经常这样做,我所用的表是相当大的.循环方法的工作原理太慢了.我玩sqldf包,没有真正的突破.我会喜欢使用一些data.table的魔法,我需要你的帮助:-).我认为需要的是某种自我加入,条件是t值的差异小于阈值.
跟进:
我有一个后续的问题:在我的申请中,这个加入是一遍又一遍地完成的. v的变化,但是t和n总是相同的.所以我正在考虑以某种方式存储哪些行属于一起.任何想法如何聪明地做到这一点?
解决方法
尝试以下:
unique(merge(DT,DT,by="n")[abs(t.x - t.y) <= 10,list(n,sum(v.x * abs(t.x - t.y))),by=list(t.x,v.x)])
上述细目:
您可以将表与自身合并,输出也将是一个data.table.请注意,列名称将被赋予.x和.y的后缀
merge(DT,by="n")
…您可以像任何DT一样过滤和计算
# this will give you your desired rows [abs(t.x - t.y),] # this is the expression you outlined [ ...,sum(v.x * abs(t.x - t.y)) ] # summing by t.x and v.x [ ...,...,v.x)]) ]
然后最后将其全部包含在唯一的中以删除任何重复的行.
更新:这应该是一个评论,但太长
下面的行是什么匹配您的输出.这个和这个答案顶部的唯一区别是总和(v.y * …)中的术语v.y,但是by语句仍然使用v.x.是有意的吗?
unique(merge(DT,sum(v.y * abs(t.x - t.y))),v.x)])