r - 如何做一个 BETWEEN 合并 data.table 的方式?

标签 r performance data.table

我有两个 data.tables,每个大小为 5-10GB。它们看起来类似于以下内容。

library(data.table)
A <- data.table(
  person = c(1,1,1,2,3,3,3,3,4,4),
  datetime = c(
    '2015-04-06 14:22:18',
    '2015-04-07 02:55:32',
    '2015-11-21 10:16:05',
    '2015-10-03 13:37:29',
    '2015-02-26 23:51:56',
    '2015-05-16 18:21:44',
    '2015-06-02 04:07:43',
    '2015-11-28 15:22:36',
    '2015-01-19 04:10:22',
    '2015-01-24 02:18:11'
  )
)

B <- data.table(
  person = c(1,1,3,4,4,5),
  datetime2 = c(
    '2015-04-06 14:24:59',
    '2015-11-28 15:22:36',
    '2015-06-02 04:07:43',
    '2015-01-19 06:10:22',
    '2015-01-24 02:18:18',
    '2015-04-06 14:22:18'
  )
)

A$datetime <- as.POSIXct(A$datetime)
B$datetime2 <- as.POSIXct(B$datetime2)

想法是在 B 中找到日期时间在 A 中匹配行的 0-10 分钟内的行(匹配由人完成)并在 A 中标记它们。问题是我怎样才能最有效地使用数据表?

一种方案是只根据[I]person[/I]连接两个数据表,然后计算时间差,找到时间差在0到600秒之间的行,最后将后者与答:

setkey(A,person)
AB <- A[B,.(datetime,
            datetime2,
            diff = difftime(datetime2, datetime, units = "secs"))
        , by = .EACHI]
M <- AB[diff < 600 & diff > 0]
setkey(A, person, datetime)
setkey(M, person, datetime)
M[A,]

这给了我们正确的结果:

    person            datetime           datetime2     diff
 1:      1 2015-04-06 14:22:18 2015-04-06 14:24:59 161 secs
 2:      1 2015-04-07 02:55:32                <NA>  NA secs
 3:      1 2015-11-21 10:16:05                <NA>  NA secs
 4:      2 2015-10-03 13:37:29                <NA>  NA secs
 5:      3 2015-02-26 23:51:56                <NA>  NA secs
 6:      3 2015-05-16 18:21:44                <NA>  NA secs
 7:      3 2015-06-02 04:07:43                <NA>  NA secs
 8:      3 2015-11-28 15:22:36                <NA>  NA secs
 9:      4 2015-01-19 04:10:22                <NA>  NA secs
10:      4 2015-01-24 02:18:11 2015-01-24 02:18:18   7 secs

但是,我不确定这是否是最有效的方法。具体来说,我正在使用 AB[diff < 600 & diff > 0]我假设它会运行矢量搜索而不是二分搜索,但我想不出如何使用二分搜索来做到这一点。

此外,我不确定是否转换为 POSIXct是计算时间差的最有效方法。

非常感谢任何关于如何提高效率的想法。

最佳答案

data.table 的滚动连接非常适合这个任务:

B[, datetime := datetime2]
setkey(A,person,datetime)
setkey(B,person,datetime)
B[A,roll=-600]

   person           datetime2   datetime
 1:      1 2015-04-06 14:24:59 1428319338
 2:      1                  NA 1428364532
 3:      1                  NA 1448090165
 4:      2                  NA 1443868649
 5:      3                  NA 1424983916
 6:      3                  NA 1431789704
 7:      3 2015-06-02 04:07:43 1433207263
 8:      3                  NA 1448713356
 9:      4                  NA 1421629822
10:      4 2015-01-24 02:18:18 1422055091

与预期输出的唯一区别是它检查时间差是否小于或等于 10 分钟 (<=)。如果这对您不利,您可以删除相等的匹配项

关于r - 如何做一个 BETWEEN 合并 data.table 的方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32483003/

相关文章:

r - 如何让 RStudio 在遇到错误后继续执行代码

android - 如何避免从 image_view 中的数组中随机化图像?

java - 大型电子表格的 Apache POI Java Excel 性能

r - 通过多个分组顺序变量折叠和粘贴文本

r - 如何传递 R 函数参数以从 df 中选择行

java - 字符串到数字转换的性能问题

安卓 : Merging/concatenating two audio files hangs up the application

r - 按列和引用绑定(bind) data.tables 列表

r - data.table 中针对不同列组合的多个聚合的灵活混合

r - 保存 R 中循环内生成的绘图