我在一个数据框中有一个大的时间序列full
,在不同的数据框中有一个时间戳列表test
。我需要full
用围绕时间戳的数据点进行子集化test
。我的第一直觉(作为一个 R 菜鸟)是写下面的,这是错误的
subs <- subset(full,(full$dt>test$dt-i) & (full$dt<test$dt+i))
查看结果,我意识到 R 同时遍历两个向量,给出了错误的结果。我的选择是编写如下循环:
subs<-data.frame()
for (j in test$dt)
subs <- rbind(subs,subset(full,full$dt>(j-i) & full$dt<(j+i)))
我觉得可能有更好的方法来做循环,这篇文章恳请我们尽可能避免 R 循环。另一个原因是我可能会遇到性能问题,因为这将是优化算法的核心。大师的任何建议将不胜感激。
编辑:
这是一些可重现的代码,它们显示了错误的方法以及可行但可能更好的方法。
#create a times series
full <- data.frame(seq(1:200),rnorm(200,0,1))
colnames(full)<-c("dt","val")
#my smaller array of points of interest
test <- data.frame(seq(5,200,by=23))
colnames(test)<-c("dt")
# my range around the points of interset
i<-3
#the wrong approach
subs <- subset(full,(full$dt>test$dt-i) & (full$dt<test$dt+i))
#this works, but not sure this is the best way to go about it
subs<-data.frame()
for (j in test$dt)
subs <- rbind(subs,subset(full,full$dt>(j-i) & full$dt<(j+i)))
编辑:我更新了这些值以更好地反映我的用例,并且我看到 @mrdwab 的解决方案出人意料地大幅领先。
我正在使用来自@mrdwab 的基准代码,初始化如下:
set.seed(1)
full <- data.frame(
dt = 1:15000000,
val = floor(rnorm(15000000,0,1))
)
test <- data.frame(dt = floor(runif(24,1,15000000)))
i <- 500
基准是:
test replications elapsed relative
2 mrdwab 2 1.31 1.00000
3 spacedman 2 69.06 52.71756
1 andrie 2 93.68 71.51145
4 original 2 114.24 87.20611
完全出乎意料。头脑=炸毁。有人可以在这个黑暗的角落里阐明一些光,并启发正在发生的事情。
重要提示:正如@mrdwab 下面所指出的,他的解决方案仅在向量为整数时才有效。如果没有,@spacedman 有正确的解决方案