merge.xts具有大量列的性能

时间:2013-05-15 09:32:42

标签: r xts

下面的函数采用CSV文件的文件夹(每个文件是具有日期时间,开放,高,低,关闭列的金融时间序列),并为每个开盘价,最高价,最低价,收盘价创建一个XTS对象,其中每个XTS列是单独的安全性。对于我的用例,这种表示允许更方便和更快速的处理(相对于每个文件的单个XTS)。

require(quantmod)

LoadUniverseToEnv <- function(srcDir, env) {
  fileList <- list.files(srcDir)
  if (length(fileList) == 0)
    stop("No files found!")

  env$op <- NULL
  env$hi <- NULL
  env$lo <- NULL
  env$cl <- NULL
  cols <- NULL

  for (file in fileList) {
    filePath <- sprintf("%s/%s", srcDir, file)
    if (file.info(filePath)$isdir == FALSE) {
      x <- as.xts(read.zoo(filePath, header=TRUE, sep=",", tz=""))
      cols <- c(sub("_.*", "", file), cols)
      # do outer join
      env$op <- merge(Op(x), env$op)
      env$hi <- merge(Hi(x), env$hi)
      env$lo <- merge(Lo(x), env$lo)
      env$cl <- merge(Cl(x), env$cl)
      cat(sprintf("%s : added: %s from: %s to: %s\n", as.character(Sys.time()), file, start(x), end(x)))
    }
  }
  colnames(env$op) <- cols
  colnames(env$hi) <- cols
  colnames(env$lo) <- cols
  colnames(env$cl) <- cols
}

性能适用于有限数量的文件,但随着XTS对象的宽度线性减慢,因此成为大型数据集的问题。合并期间的瓶颈是CPU,当一个新列被附加到四个对象中的每一个时(例如100ms最初减慢1ms /列)

由于它是CPU绑定的,我首先想到的是通过合并n批文件然后合并结果进行并行化,但我想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:0)

我发现的最佳解决方案是合并“块”。例如,假设100列,合并为10个XTS对象,每个10列,然后合并这10个对象,可以显着提高性能。

下面的示例显示,当合并2000 xts对象,每行1000行和相同的索引时,性能提高了1500%。

示例:

require(xts)
require(foreach)

nCols <- 2000
nRows <- 1000

x <- xts(runif(nRows), order.by=as.Date(seq(1:nRows)))
xList <- list()
for (i in 1:nCols)
  xList[[i]] <- x

testA <- function() {
  merged <- NULL
  for (x in xList)  
    merged <- merge(x, merged)
  colnames(merged) <- 1:length(xList)
  merged
}

testB <- function() {
  nChunks <- floor(sqrt(length(xList)))
  idx <- split(1:n, sort(1:n %% nChunks))

  merged <- foreach (chunk = 1:nChunks, .combine = "merge") %do% {
    merged <- foreach (i = idx[[chunk]], .combine = "merge") %do% {
      xList[[i]]
    }
    merged
  }
  colnames(merged) <- 1:length(xList)
  merged
}

print("Test A")
print(system.time(resultA <- testA()))
print("Test B")
print(system.time(resultB <- testB()))
print(sprintf("Identical : %s", identical(resultA, resultB)))
print(sprintf("Dimensions: %dx%d", ncol(resultA), nrow(resultA)))

<强>输出:

[1] "Test A"
   user  system elapsed
  33.12    3.18   36.30
[1] "Test B"
   user  system elapsed
   2.28    0.01    2.31
[1] "Identical : TRUE"
[1] "Dimensions: 2000x1000"

请注意,foreach未并行运行。