合并大量 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 可能会有所帮助
我试过merge
、rbind
和cbind
。不幸的是,它们都失败了,内存使用量从 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]]
如果你想rbind
data.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)。大多数值将是NA
。 cbind.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 对象的主要内容,如果未能解决你的问题,请参考以下文章