我有一个如下所示的数据表,我想在另一个时间戳矢量的5s时间范围内汇总所有值。
如果我的描述让您感到困惑,请参阅以下玩具示例
trade_hist <-data.table(timestamp=seq(1,200,2),value=rep(1:5,20))
TS <- seq(2,200,2)
> head(trade_hist)
timestamp value
1: 1 1
2: 3 2
3: 5 3
4: 7 4
5: 9 5
6: 11 1
> head(TS)
[1] 2 4 6 8 10 12
我最终想要在TS中创建带有timetamp的新表,并使用特定条件聚合原始表中的值(例如,在该时间戳之前的5s时间范围内汇总所有值)。我可以使用以下代码完成此任务:
list_of_values <- vector("list",length(TS))
for(i in 1:length(TS)){
ts <- TS[i]
tmp <- trade_hist[(ts-timestamp <= 5) & ts-timestamp > 0]
tmp <- tmp[,.(sumVal=sum(value))]
list_of_values[[i]] <- tmp
}
newcol <- rbindlist(list_of_values)
result_wanted <- cbind(TS,newcol)
> head(result_wanted)
TS sumVal
1: 2 1
2: 4 3
3: 6 6
4: 8 9
5: 10 12
6: 12 10
例如,当TS = 6时,回顾原始表5s范围之前我们有值= 1,2,3因此总和是6;当TS = 8时,回顾原始表我们有值= 2,3,4,总和是9。
然而上面的代码对于更大的表来说效率极低,还有其他方法吗? THX!
答案 0 :(得分:2)
感谢@MichaelChirico建议forverlap 我使用forverlap为我的问题编写了一个解决方案,它非常快!
x <- data.table(start=TS,end=TS)
y <- trade_hist[,.(start=timestamp,end=timestamp+5,value)]
setkey(y, start, end)
tmp <- foverlaps(x, y, type="within")
result <- tmp[,.(value=sum(value)),by=i.start]
setnames(result,"i.start","timestamp")
答案 1 :(得分:1)
使用dplyr
,
sumVal <- sapply(TS, function(x){
sum(trade_hist %>%
filter(timestamp >= x-5, timestamp <= x) %>%
select(value))
})
result_wanted <- data.frame(TS, sumVal)
将比原版快得多。如果您的数据非常庞大,data.table
或Rcpp
可能会让它更快。
请注意,如果TS
和trade_hist$timestamp
实际上是日期时间对象,则它们必须采用可以处理减法和大于/小于运算符的格式,或者那些操作需要改为合适的。如果基础lubridate
/ chron
没有削减它,POSIXlt
或POSIXct
可能会提供您所需的内容。