将R中的数据表与表外的信息进行聚合

时间:2016-01-14 21:57:51

标签: r data.table

我有一个如下所示的数据表,我想在另一个时间戳矢量的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!

2 个答案:

答案 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.tableRcpp可能会让它更快。

请注意,如果TStrade_hist$timestamp实际上是日期时间对象,则它们必须采用可以处理减法和大于/小于运算符的格式,或者那些操作需要改为合适的。如果基础lubridate / chron没有削减它,POSIXltPOSIXct可能会提供您所需的内容。