【问题标题】:rolling joins in data.table with multiple matches具有多个匹配项的 data.table 中的滚动联接
【发布时间】:2013-06-17 11:58:27
【问题描述】:

我有一个关于滚动连接的评论/问题
设 X,Y 为:

set.seed(123);
X <- data.table(x=c(1,1,1,2,2),y=c(T,T,F,F,F),t=as.POSIXct("08:00:00.000",format="%H:%M:%OS")+sample(0:999,5,TRUE)/1e3)
Y <- copy(X)
set.seed(123)
Y[,`:=`(IDX=.I,t=t+sample(c(-5:5)/1e3,5,T))]
Y <- rbindlist(list(Y, X[5,][,IDX:=6][,t:=t+0.001], X[5,][,IDX:=7][,t:=t+0.002]))
setkey(X,x,y,t)
setkey(Y,x,y,t)

这里XYx,y,t排序

R) X
   x     y                       t
1: 1 FALSE 2013-06-20 08:00:00.407
2: 1  TRUE 2013-06-20 08:00:00.286
3: 1  TRUE 2013-06-20 08:00:00.788
4: 2 FALSE 2013-06-20 08:00:00.882
5: 2 FALSE 2013-06-20 08:00:00.940
R) Y
   x     y                       t IDX
1: 1 FALSE 2013-06-20 08:00:00.407   3
2: 1  TRUE 2013-06-20 08:00:00.284   1
3: 1  TRUE 2013-06-20 08:00:00.791   2
4: 2 FALSE 2013-06-20 08:00:00.886   4
5: 2 FALSE 2013-06-20 08:00:00.940   6
6: 2 FALSE 2013-06-20 08:00:00.942   7
7: 2 FALSE 2013-06-20 08:00:00.945   5

来自

执行Y[X, roll=-0.005] 得到你

R) Y[X, roll=-0.005]
       x     y                       t IDX
    1: 1 FALSE 2013-06-20 08:00:00.407  NA => due to precision the roll is no match
    2: 1  TRUE 2013-06-20 08:00:00.286  NA => ok 
    3: 1  TRUE 2013-06-20 08:00:00.788   2 => ok (x,y) matched and 788-791=-3
    4: 2 FALSE 2013-06-20 08:00:00.882   4 => same
    5: 2 FALSE 2013-06-20 08:00:00.940   6 => NOT AN EXACT MATCH (precision)

所以我本来希望在最后一行得到更多行,因为“mult”的默认行为是“all”,X 的最后一行与Y5,6, may be 7 行匹配

【问题讨论】:

  • 我对此很感兴趣,因为如果我们能够获得这些额外的行,我们应该能够处理窗口连接并计算滚动中位数、平均值或其他任何东西
  • 这对我来说听起来像是一个功能请求(不过我会使用一个非常简单的例子,比如d = data.table(a = c(1.0,2.0,2.0), by = c(1:3), key = 'a'); d[J(2.1), ...],因为这个很难理解)

标签: r data.table rolling-computation


【解决方案1】:

第一行

对于X 的第一行,只有Y 的第一行匹配xy,所以Y 的第一行将匹配如果Y$t[1]X$t[1] 和@987654328 之间@ 但实际上 Y$t[1] &lt; X$t[1] 如下所示:

> X$t[1] - Y$t[1]
Time difference of 0.0009999275 secs

需要一个正的roll= 值,其幅度至少等于上述差值,以便在第 1 行获得非 NA。例如

> Y[X, roll=0.001]
   x     y                   t IDX
1: 1 FALSE 2013-06-20 08:00:00   3
2: 1  TRUE 2013-06-20 08:00:00  NA
3: 1  TRUE 2013-06-20 08:00:00  NA
4: 2 FALSE 2013-06-20 08:00:00  NA
5: 2 FALSE 2013-06-20 08:00:00  NA

请注意,您可以像这样使用rollends= 来强制它:

> Y[X, roll = -0.005, rollends = TRUE]
   x     y                   t IDX
1: 1 FALSE 2013-06-20 08:00:00   3
2: 1  TRUE 2013-06-20 08:00:00  NA
3: 1  TRUE 2013-06-20 08:00:00   2
4: 2 FALSE 2013-06-20 08:00:00   4
5: 2 FALSE 2013-06-20 08:00:00   6

最后一行

对于X 的最后一行,只有Y 的第5 行匹配,而不是5、6 和7,因为只有最近的符合条件的行是匹配的。 mult= 仅适用于多个匹配项,通常不适用于 roll=(见底部示例以了解例外情况):

还要注意Y 的第 5、6 和 7 行的时间不同。它们的次数越来越多,因此它们不可能都匹配:

> dput(Y[["t"]])
structure(c(1371729600.407, 1371729600.285, 1371729600.791, 1371729600.887, 
1371729600.941, 1371729600.942, 1371729600.945), class = c("POSIXct", 
"POSIXt"))

即使Y 的第 5、6 和 7 行具有相同的时间,如果这些时间与 X 的最后一行中的时间不同,那么也只能得到一行。

> # times in rows 5, 6 and 7 of Y2 are same
> Y2 <- copy(Y)
> Y2[, t:= t[c(1:4, 5, 5, 5)]]
> setkey(Y2, x, y, t)
> Y2[X, roll = -0.005]
   x     y                   t IDX
1: 1 FALSE 2013-06-20 08:00:00  NA
2: 1  TRUE 2013-06-20 08:00:00  NA
3: 1  TRUE 2013-06-20 08:00:00   2
4: 2 FALSE 2013-06-20 08:00:00   4
5: 2 FALSE 2013-06-20 08:00:00   6

只有当 'Y' 的第 5、6 和 7 行具有相同的时间 并且 X 的最后一行也有那个时间,在这种情况下 @ 987654345@可以申请:

> # time in row 5 of X2 same as the times in rows 5, 6 and 7 of Y2
> X2 <- copy(X)
> X2[, t:=c(t[1:4], Y2[["t"]][5])]
> Y2[X2, roll = -0.005]
   x     y                   t IDX
1: 1 FALSE 2013-06-20 08:00:00  NA
2: 1  TRUE 2013-06-20 08:00:00  NA
3: 1  TRUE 2013-06-20 08:00:00   2
4: 2 FALSE 2013-06-20 08:00:00   4
5: 2 FALSE 2013-06-20 08:00:00   6
6: 2 FALSE 2013-06-20 08:00:00   7
7: 2 FALSE 2013-06-20 08:00:00   5
> 
> Y2[X, roll = -0.005, mult = "first"]
   x     y                   t IDX
1: 1 FALSE 2013-06-20 08:00:00  NA
2: 1  TRUE 2013-06-20 08:00:00  NA
3: 1  TRUE 2013-06-20 08:00:00   2
4: 2 FALSE 2013-06-20 08:00:00   4
5: 2 FALSE 2013-06-20 08:00:00   6

它的工作原理从文档中并不清楚,我不得不通过反复试验来发现它是如何工作的。 ?data.table 确实说“通常,x 的键中不应该有重复项”(在我们的示例中,这里的 x 是 Y)所以开发人员可能希望为此保留它未定义情况并对未来的变化持开放态度。

您所描述的使用mult= 的想法似乎是一个非常有趣的想法,但它似乎不是目前的工作方式。也许将来会。

【讨论】:

  • 已将我的 cmets 移至答案。
  • 我认为 OP 认为因为在 d = data.table(a = c(1,2,2), b = c(1:3), key = 'a') d[J(2)] 匹配两个 2,所以当 mult 设置为 "all" 时,d[J(2.1), roll = 1] 应该匹配两个 2
  • 我添加了一些额外的探索性代码来查看在各种情况下会发生什么。请参阅最后添加的内容。
猜你喜欢
  • 2018-01-16
  • 2021-05-10
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多