合并大量 xts 对象

Posted

技术标签:

【中文标题】合并大量 xts 对象【英文标题】:merging a large list of xts objects 【发布时间】:2012-08-15 06:03:50 【问题描述】:

我有一个 xts 对象的列表,它们是互斥天数。我想将merge 列表合并为一个大的xts 对象。我这样做的尝试是“

merged_reg_1_min_prices <- do.call(cbind, reg_1_min_prices)

但是这似乎内存不足。 reg_1_min_prices 是 6,000 天的 1 分钟在互斥天返回,所以它不是很大。有谁知道如何解决这个问题?

要明确:reg_1_min_prices 包含相互排斥的日期,每天有 1 分钟的价格,列表中的每个条目都是一个 xts 对象。

【问题讨论】:

reg_1_min_prices 是 6,000 个 xts 对象的列表,其中每个列表元素是一天的 1 分钟数据吗? 是的。抱歉,让我将其添加到问题中 您确定要cbind 而不是rbind?如果您想rbind 数据,this function 可能会有所帮助 我试过mergerbindcbind。不幸的是,它们都失败了,内存使用量从 aourn 4 gigs 增加到大约 60 gigs。 我上面引用的函数在FinancialInstrument:::getSymbols.FI 中使用,它可以很好地加载和合并大量天数的高频数据。 【参考方案1】:

我使用Dominik在his answer到this question提供的策略

我已经把它变成了function 在我的qmao 包中。这段代码也是getSymbols.FI的核心,在FinancialInstrument package中。

do.call.rbind <- function(lst) 
  while(length(lst) > 1) 
    idxlst <- seq(from=1, to=length(lst), by=2)
    lst <- lapply(idxlst, function(i) 
      if(i==length(lst))  return(lst[[i]]) 
      return(rbind(lst[[i]], lst[[i+1]]))
    )
  
  lst[[1]]

如果你想rbinddata.frames,@JoshuaUlrich提供了一个优雅的解决方案here


据我所知(无需仔细观察)内存对于所提供的三种解决方案(@JoshuaUlrich's、@Alex's 和 qmao::do.call.rbind)中的任何一种都不是问题。所以,归根结底是速度……

library(xts)
l <- lapply(Sys.Date()-6000:1, function(x) 
    N=60*8;xts(rnorm(N),as.POSIXct(x)-seq(N*60,1,-60)))
GS <- do.call.rbind
JU <- function(x) Reduce(rbind, x)
Alex <- function(x) do.call(rbind, lapply(x, as.data.frame)) #returns data.frame, not xts

identical(GS(l), JU(l)) #TRUE

library(rbenchmark)
benchmark(GS(l), JU(l), Alex(l), replications=1)
     test replications elapsed relative user.self sys.self user.child sys.child
3 Alex(l)            1  89.575 109.9080    56.584   33.044          0         0
1   GS(l)            1   0.815   1.0000     0.599    0.216          0         0
2   JU(l)            1 209.783 257.4025   143.353   66.555          0         0

do.call.rbind 显然在速度上获胜。

【讨论】:

【参考方案2】:

您不想使用merge,因为这将返回一个包含 6000 列的对象,其中每个列表元素中的每一行都有一行(在我的示例中为 2,880,000)。大多数值将是NAcbind.xts 只是使用一些默认参数值调用 merge.xts,所以你也不想使用它。

我们知道通过do.call 调用rbind.xts 引起的内存问题。 Jeff 确实有更高效的代码,但它是一个不公开的原型。

@GSee's solution 的替代方法是使用Reduce。这需要一段时间才能在我的笔记本电脑上运行,但即使只有 4GB,内存也不是问题。

library(xts)
l <- lapply(Sys.Date()-6000:1, function(x) 
  N=60*8;xts(rnorm(N),as.POSIXct(x)-seq(N*60,1,-60)))
x <- Reduce(rbind, l)

【讨论】:

太棒了!什么是减少?我似乎找不到它的 R 参考 @Alex:它是基础包中的一个函数。见?Reduce +1 用于解释为什么 cbind 不是 OP 想要的。【参考方案3】:

这里是如何有效地做到这一点:将每个 xts 对象转换为 data.frame 和简单的 rbind 它们。这几乎不会增加内存使用量。如有必要,只需从 data.frame 创建一个新的 xts 对象

【讨论】:

我不认为do.call.rbind 使用太多内存,而且对于我测试过的数据来说,它的速度要快很多(甚至不包括转换回xts 的时间)。 好吧,让我试一试。你碰巧知道普通的 rbind 是怎么搞砸的吗? 不,但我敢打赌@JoshuaUlrich 会。如果我没记错的话,Jeff 有一些未提交的代码可以更有效地执行此操作。

以上是关于合并大量 xts 对象的主要内容,如果未能解决你的问题,请参考以下文章

在循环中添加 xts 对象

将大量 Spark 数据帧合并为一个

如何将大量小文件合并为一个文件

合并大量data.frames [重复]

使用熊猫循环合并大量csv文件[重复]

合并大量小文件以最大化可恢复性的最佳方法是啥