找到数据集与参考(更大)数据集的最接近时间的有效编程方法是什么

What is an efficient programming way to find the closest time of a dataset to a reference (larger) dataset

我正在寻找一种有效的方法来查找小型数据集 (x) 与大型数据集 (a) 的最接近时间。结果必须是 (a) 长度的索引。我已经创建了一个非常好的函数,但是,它对于大数据来说绝对没用,因为它需要几天的时间来处理。

Here is my function: function(x, a, which = TRUE,na.rm=FALSE){
  if("POSIXt" %in% class(x)) x <- as.numeric(x)
  if("POSIXt" %in% class(a)) a <- as.numeric(a)
  sapply(a, function(y) DescTools::Closest(x, y, which = TRUE,na.rm=FALSE)[1])
}

数据集x和a都经过过滤,因此没有一致的时间戳,但它们是根据相同的要求过滤的。

向量 a 包含长度为 16020209 的 20 Hz 数据,x 包含长度为 26908 的 30 秒数据。

非常感谢任何建议!谢谢:)

我会使用类似 SQL 完全连接的东西来完成这个任务,因为第二个 df 很小——尽管它取决于你的数据大小和 ram。这是一个带有测试数据的简单示例:

library(dplyr)

# demo tibbles
tab1 <- tibble::tribble(
  ~time_1, ~VALUE_1,
  "2020-11-01",      268L,
  "2020-11-02",      479L,
  "2020-11-03",      345L,
  "2020-11-04",      567L,
  "2020-11-05",      567L) %>% 
    dplyr::mutate(time_1 = as.Date(time_1))

tab2 <- tibble::tribble(
  ~time_2, ~VALUE_2,
  "2020-11-01",      268L,
  "2020-11-02",      479L) %>% 
    dplyr::mutate(time_2 = as.Date(time_2))

# calculations
tab1 %>% 
  dplyr::mutate(ID = dplyr::row_number()) %>% # Build ID from row number
  dplyr::full_join(tab2, by = character()) %>% 
  dplyr::mutate(DIF = abs(time_1 - time_2)) %>%
  dplyr::group_by(ID) %>%
  dplyr::slice_min(order_by = DIF, n = 1) 

  time_1     VALUE_1    ID time_2     VALUE_2 DIF   
  <date>       <int> <int> <date>       <int> <drtn>
1 2020-11-01     268     1 2020-11-01     268 0 days
2 2020-11-02     479     2 2020-11-02     479 0 days
3 2020-11-03     345     3 2020-11-02     479 1 days
4 2020-11-04     567     4 2020-11-02     479 2 days
5 2020-11-05     567     5 2020-11-02     479 3 days

如果结果证明尺寸有问题,您可以将大 data.frame 分成较小的一次,然后用循环将 运行 分开。在这种情况下,并行处理将是一个很好的选择,因为通过拆分大型 DF 计算可以 运行 独立。

可以使用来自 data.table 的滚动连接:

library(data.table)
set.seed(1)  # reproduciblity on Whosebug
DF_A <- data.table(x = seq(-500, by = 0.5, length.out = 26908),
                   idx = seq_len(26908))

DF_HZ <- data.table(x = round(runif(16020209, first(DF_A$x), last(DF_A$x)), 3),
                    idx_hz = seq_len(16020209))

DF_HZ[, x_hz := x + 0] # so we can check
DF_A[, x_a := x + 0] # so we can check


setkey(DF_A, x)
setkey(DF_HZ, x)

# The order(idx_hz) returns the result in the same order as 
# DF_HZ but it is not necessary to match joins.
DF_A[DF_HZ, roll = "nearest"][order(idx_hz)]
#>                   x   idx     x_a   idx_hz      x_hz
#>        1:  3072.021  7145  3072.0        1  3072.021
#>        2:  4506.369 10014  4506.5        2  4506.369
#>        3:  7206.883 15415  7207.0        3  7206.883
#>        4: 11718.574 24438 11718.5        4 11718.574
#>        5:  2213.328  5428  2213.5        5  2213.328
#>       ---                                           
#> 16020205: 10517.477 22036 10517.5 16020205 10517.477
#> 16020206: 11407.776 23817 11408.0 16020206 11407.776
#> 16020207: 12051.919 25105 12052.0 16020207 12051.919
#> 16020208:  3482.463  7966  3482.5 16020208  3482.463
#> 16020209:   817.366  2636   817.5 16020209   817.366

reprex package (v0.3.0)

于 2020-11-11 创建

在我的机器上,上述(不包括虚拟数据的创建)大约需要 3 秒。