【问题标题】:Aggregating data table in R with information outside the tableR中的数据表与表外的信息聚合
【发布时间】:2016-01-14 21:57:50
【问题描述】:

我有一个如下所示的数据表,我想汇总另一个时间戳向量的 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 中一样创建带有时间戳的新表,并在特定条件下聚合原始表中的值(比如在该时间戳之前的 5 秒时间范围内总结所有值)。我可以使用以下代码完成此操作:

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范围之前,我们有value=1,2,3,因此总和为6;当 TS=8 时,回看原来的表我们有 value=2,3,4,sum 为 9。

但是上面的代码对于更大的表来说效率极低,还有其他方法吗?谢谢!

【问题讨论】:

  • 这不是很可重现。
  • 请使用dput 编辑您的数据。不过,一般来说,这些操作看起来是可矢量化的;只需在没有循环的情况下运行相同的东西。
  • 你会让你的例子更小并显示你想要的输出吗?
  • @DavidArenburg 描述已编辑。请帮忙!
  • @alistaire 如果你能提供一个矢量化的例子,那就太好了。谢谢!

标签: r data.table


【解决方案1】:

感谢@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")

【讨论】:

    【解决方案2】:

    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 实际上是日期时间对象,则它们需要采用可以处理减法和大于/小于运算符的格式,或者这些操作需要更改为合适的一个。 lubridatechron 可能有你需要的,如果基础 POSIXlt/POSIXct 没有削减它。

    【讨论】:

    • 谢谢,但我认为我的版本比这更快...我检查了更大的表
    • 如果你将trade_hist 包裹在dplyr::tbl_df 中,我的时间会比原来的快2/3 到10-15%。老实说,for-loop 的性能给我留下了深刻的印象;他们可以变得更慢。真的,如果时间是首要考虑因素,Rcpp 就是戏,但这超出了我目前的专业知识。
    • *还将data.frame(TS, sumVal) 改回cbind(TS, sumVal) 以获得最大速度。打印格式略有不同,但数据相同。
    • 指定参数名称也有帮助。速度提高 30%:sumVal &lt;- sapply(X = TS, FUN = function(x){sum(select(.data = filter(.data = trade_hist, ... = timestamp &gt;= x-5 &amp; timestamp &lt;= x), ... = value))}) 另请参阅 this post 了解更多选项。
    猜你喜欢
    • 2019-03-23
    • 1970-01-01
    • 2015-06-28
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2011-01-12
    • 2018-07-11
    相关资源
    最近更新 更多