什么是找到数据集最接近参考较大数据集时间的有效编程方式

问题描述

我正在寻找一种有效的方法来查找与大数据集(a)相比最接近小数据集(x)的时间。结果必须是(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,na.rm=FALSE)[1])
}

x和a数据集都经过过滤,因此没有一致的时间间隔,但在相同的条件下进行了过滤。

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

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

解决方法

一个人可以使用data.table中的滚动联接:

library(data.table)
set.seed(1)  # reproduciblity on Stackoverflow
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 s。

,

由于第二个df很小,因此我将使用类似SQL完全连接的方式执行此任务-尽管这取决于您的数据大小和内存。这是一个包含测试数据的简单示例:

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,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计算可以独立运行。