如何使用 data.table 在日期范围内执行连接?

Posted

技术标签:

【中文标题】如何使用 data.table 在日期范围内执行连接?【英文标题】:How to perform join over date ranges using data.table? 【发布时间】:2015-02-13 18:42:28 【问题描述】:

如何使用 data.table 执行以下操作(直接使用 sqldf)并获得完全相同的结果:

library(data.table)

whatWasMeasured <- data.table(start=as.POSIXct(seq(1, 1000, 100),
    origin="1970-01-01 00:00:00"),
    end=as.POSIXct(seq(10, 1000, 100), origin="1970-01-01 00:00:00"),
    x=1:10,
    y=letters[1:10])

measurments <- data.table(time=as.POSIXct(seq(1, 2000, 1),
    origin="1970-01-01 00:00:00"),
    temp=runif(2000, 10, 100))

## Alternative short names for data.tables
dt1 <- whatWasMeasured
dt2 <- measurments

## Straightforward with sqldf    
library(sqldf)

sqldf("select * from measurments m, whatWasMeasured wwm
where m.time between wwm.start and wwm.end")

【问题讨论】:

这能解决您的问题吗? ***.com/questions/5123197/… @DavidRobinson 谢谢。这个问题我其实已经看过了,可惜我的数据量很大,真的更喜欢快速的data.table解决方案…… 我知道这有点不真实,但我是唯一一个得到 1969 年 12 月 31 日约会的人吗?不应该是 1970 年 1 月 1 日吗? @SerbanTanasa 时区问题我猜... 【参考方案1】:

您可以使用foverlaps() 函数,它可以有效地实现间隔连接。在您的情况下,我们只需要一个用于 measurments 的虚拟列。

注意 1: 您应该安装 data.table - v1.9.5 的开发版本,因为 foverlaps() 的错误已在此处修复。你可以找到安装说明here。

注意 2: 为了方便起见,我会在此处致电 whatWasMeasured = dt1measurments = dt2

require(data.table) ## 1.9.5+
dt2[, dummy := time]

setkey(dt1, start, end)
ans = foverlaps(dt2, dt1, by.x=c("time", "dummy"), nomatch=0L)[, dummy := NULL]

更多信息请参见?foverlaps,性能比较请参见this post。

【讨论】:

有什么办法可以让我们摆脱某种 %between% 语句?很难让 dt2[time %between% dt1[, list(start,end)]] 像我希望的那样工作。 @SerbanTanasa,看看the post 我已经在我的答案中链接了。它还比较了使用 between 的解决方案的性能。 感谢您的回答。伟大的。有用。非常快。唯一的小问题是它不喜欢 start 或 end 或 time 的缺失值。也许 na.rm 处理会很好。此外,在对真实数据进行此练习时,我最终得到两个额外的不需要的列,名为“start”和“end”,我在输入数据中既没有,也没有键名或任何东西...... @Samo,使用 na.omit()cols 参数(如果您使用的是 1.9.5)。会考虑na.rm 的论点,谢谢。我不明白 - 您的 data.table whatWasMeasured 有两列 startend,并且 sqldf 输出在您的帖子中的示例中也有相同的列。 @Arun 谢谢。是的,请忽略我关于幻象启动和意外出现的评论。实际上它们并没有出现。感谢您的理解。我在“真实”数据而不是上面的玩具示例上对此进行测试,显然我没有刷新所有对象......

以上是关于如何使用 data.table 在日期范围内执行连接?的主要内容,如果未能解决你的问题,请参考以下文章

R中按日期范围设置的子集data.table

如何创建一个变量,该变量是给定时间范围内连续行的总和并按 id

计算日期范围内每个日期的行数

如何使用 snowsql 在给定日期范围内构造日期数组?

如何遍历Java中的日期范围?

SQL 如何查询日期在一定范围内的数据