将时间戳数据与另一个数据集中的最接近时间相匹配。正确矢量化?更快的方式?

Posted

技术标签:

【中文标题】将时间戳数据与另一个数据集中的最接近时间相匹配。正确矢量化?更快的方式?【英文标题】:Matching timestamped data to closest time in another dataset. Properly vectorized? Faster way? 【发布时间】:2015-09-15 05:18:03 【问题描述】:

我在一个数据帧中有一个时间戳,我试图将其与第二个数据帧中最接近的时间戳匹配,以便从第二个数据帧中提取数据。有关我的方法的一般示例,请参见下文:

library(lubridate)

data <- data.frame(datetime=ymd_hms(c('2015-04-01 12:23:00 UTC', '2015-04-01 13:49:00 UTC', '2015-04-01 14:06:00 UTC' ,'2015-04-01 14:49:00 UTC')),
                   value=c(1,2,3,4))
reference <- data.frame(datetime=ymd_hms(c('2015-04-01 12:00:00 UTC', '2015-04-01 13:00:00 UTC', '2015-04-01 14:00:00 UTC' ,'2015-04-01 15:00:00 UTC', '2015-04-01 16:00:00 UTC')),
                        refvalue=c(5,6,7,8,9))

data$refvalue <- apply(data, 1, function (x)
  differences <- abs(as.numeric(difftime(ymd_hms(x['datetime']), reference$datetime)))
  mindiff <- min(differences)
  return(reference$refvalue[differences == mindiff])
)

data
#              datetime value refvalue
# 1 2015-04-01 12:23:00     1        5
# 2 2015-04-01 13:49:00     2        7
# 3 2015-04-01 14:06:00     3        7
# 4 2015-04-01 14:49:00     4        8

这很好用,只是速度很慢,因为在我的实际应用程序中参考数据帧非常大。此代码是否正确矢量化?是否有更快、更优雅的方式来执行此操作?

【问题讨论】:

在 Python 中,这正是函数 numpy.searchsorted 的用途。我找了一个 R 等价物,但到目前为止找不到.. @cxrodgers:看到该功能在此任务中的应用会很有趣。在查看了 tis 文档后,我正在挠头想知道它是如何做到的。你能找到一个 SO 工作示例吗? @BondedDust 在这里查看 Bi Rico 提供的答案:***.com/questions/8914491/… 【参考方案1】:

您可以使用“最近”选项尝试data.tables 滚动加入

library(data.table) # v1.9.6+
setDT(reference)[data, refvalue, roll = "nearest", on = "datetime"]
# [1] 5 7 7 8

【讨论】:

一行(不获取索引):setDT(data)[, refvalue := setkey(setDT(reference), datetime)[data, refvalue, roll="nearest"]] - 当实现无键连接时,这会变得更好。 是否还可以添加参考中使用的日期时间并将其添加到数据中,以检查“最近”实际上有多接近? @BetaScoo8 你可以做类似indx &lt;- setkey(setDT(reference), datetime)[data, roll = "nearest", which = TRUE] ; setDT(data)[, c("refdate", "refvalue") := reference[indx]] @BetaScoo8 顺便说一句,您不再需要键入,您现在可以使用 indx &lt;- setDT(reference)[data, roll = "nearest", which = TRUE, on = "datetime"] 创建 indx(在 v 1.9.6+ 中) 我最初从 42- 中选择了答案,但这是我最终每天都使用的方法。两者都有效。 data.tables 非常适合处理大数据【参考方案2】:

我想知道这是否能够与 data.table 解决方案的速度相匹配,但它是一个 base-R 矢量化解决方案,应该优于您的 apply 版本。而且由于它实际上并没有计算距离,它实际上可能比 data.table-nearest 方法更快。这会将间隔中点的长度添加到可能的最低值或间隔的起点以创建一组“中间休息”,然后使用findInterval 函数来处理时间。这将为reference 数据集的行创建一个合适的索引,然后可以将“refvalue”“转移”到data-object。

 data$reefvalue <- reference$refvalue[
                      findInterval( data$datetime, 
                                     c(-Inf, head(reference$datetime,-1))+
                                     c(0, diff(as.numeric(reference$datetime))/2 )) ]
 # values are [1] 5 7 7 8

【讨论】:

以上是关于将时间戳数据与另一个数据集中的最接近时间相匹配。正确矢量化?更快的方式?的主要内容,如果未能解决你的问题,请参考以下文章

使用 PySpark 连接与另一列中的两列确定的范围相匹配的数据框

如何使用 data.table 有效地计算一个数据集中的 GPS 点与另一个数据集中的 GPS 点之间的距离

如何让按钮的高度与另一个元素的高度相匹配?

如何对齐两个大小不等的时间序列numpy数组?

SQL:将时间戳与仅时间参数相匹配,以对多天的唯一时间进行分组和计数

如何根据时间戳匹配值,当时间戳不存在时,该值是前一个时间戳的值