Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/75.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 如何在条件下自联接data.table_R_Join_Data.table - Fatal编程技术网

R 如何在条件下自联接data.table

R 如何在条件下自联接data.table,r,join,data.table,R,Join,Data.table,我想在data.table中添加一个新列。此列应包含满足特定条件的所有行的另一列的总和。例如:My data.table如下所示: require(data.table) DT <- data.table(n=c("a", "a", "a", "a", "a", "a", "b", "b", "b"), t=c(10, 20, 33, 40, 50, 22, 25, 34, 11), v=c(20, 15, 16, 17, 11, 12,

我想在data.table中添加一个新列。此列应包含满足特定条件的所有行的另一列的总和。例如:My data.table如下所示:

require(data.table)
DT <- data.table(n=c("a", "a", "a", "a", "a", "a", "b", "b", "b"),
             t=c(10, 20, 33, 40, 50, 22, 25, 34, 11),
             v=c(20, 15, 16, 17, 11, 12, 20, 22, 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
在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
for(1中的i:nrow(DT))
DT[i,foo:=DT[n==DT[i]$n&abs(t-DT[i]$t)尝试以下方法:

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)])
…您可以像使用任何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
[ ... , ... , by=list(t.x, v.x)]) ]
然后最后将其全部包装在
unique
中,以删除任何重复的行


更新:这应该是一个评论,但太长了

下面的一行与您的输出相匹配。这与答案顶部的一行之间的唯一区别是
sum(v.y*…)
中的术语
v.y
,但是
by
语句仍然使用
v.x
。这是故意的吗

unique(merge(DT, DT, by="n")[abs(t.x - t.y) <= 10, list(n, sum(v.y * abs(t.x - t.y))), by=list(t.x, v.x)])

unique(merge(DT,DT,by=“n”)[abs(t.x-t.y)这是一个很好的问题。这个答案和李嘉图的答案一样是一个很好的尝试

理想情况下,为了提高效率,我们希望避免大型笛卡尔自联接。不幸的是,尚未实现。同时,使用最新的v1.8.7(未经测试):

一旦FR#203完成,上述逻辑将内置,并应成为一行程序:

setkey(DT,n,t)
DT[.(n,.(t-10,t+10),t), foo:=sum(v*abs(t-i.t))]
i
表的第二列有一个2列的列(表示中间联接)。这应该很快,因为像往常一样,
j
将对
i
的每一行求值,而无需创建一个巨大的笛卡尔自联接表


无论如何,这是当前的想法。

从您的输出来看,您似乎也有一个条件
i!=x
是否正确?否。对于第9行foo=0,因为术语abs(t-DT[i]$t)==0。但不应排除i!=x,因为我的应用程序中的计算比本例中的计算复杂一点,我需要在其中包含行x。谢谢!这比我在示例中使用for-loop方法快大约6倍。我现在将在实际数据上尝试此方法…很高兴能提供帮助…有趣的是,我使用的是
v.x
,而且看起来您您可以使用
v.y
您的计算期望的是哪一个?关于合并。您使用的是标准的合并函数。类似于DT[DT]的数据表合并应该更快,对吗?@uuazed,不,合并是
merge.data.table
我的计算是预期的v.y.再次感谢你的回答!一旦data.table v1.8.7发布,我会尝试一下FR#203已经实施了吗?我在SO中提出了以下问题,我认为它会从你提出的建议中受益。
unique(merge(DT, DT, by="n")[abs(t.x - t.y) <= 10, list(n, sum(v.y * abs(t.x - t.y))), by=list(t.x, v.x)])
setkey(DT,n,t)
DT[,from:=DT[.(n,t-10),which=TRUE,roll=-Inf,rollends=TRUE]]
DT[,to:=DT[.(n,t+10),which=TRUE,roll=+Inf,rollends=TRUE]]
DT[,foo:=0L]
for (i in 1:nrow(DT)) {
    s = seq.int(DT$from[i],DT$to[i])
    set(DT, i, "foo", DT[,sum(v[s]*abs(t[s]-t[i]))] )
}
setkey(DT,n,t)
DT[.(n,.(t-10,t+10),t), foo:=sum(v*abs(t-i.t))]