预分配内存以获取R中的列表列表

时间:2015-10-20 20:15:27

标签: r list memory-management lapply

我正在对R中的产品性能进行分析。对于每个产品,我们都会返回一个列表,其中包含几个结果汇总统计信息。这都是在lapply()循环中完成的。整个过程中最昂贵的操作实际上是用于存储分析结果的列表的内存分配。有没有办法为列表列表预先分配内存?我已经看到它完成了向量和矩阵,但没有列出列表。

当前代码示例:

# Merely to generate example product names
product_names <- as.vector(
  outer(outer(LETTERS[seq(1, 26, 1)], LETTERS[seq(1, 26, 1)], paste, sep=""),
        LETTERS[seq(1, 26, 1)], paste, sep = ""
  )
)

model_result <- lapply(product_names, function(product_name){
  # Do analysis here
  # The actual code takes data from a data.table and performs the analysis
  # This code is provided to illustrate what is being returned
  result1 <- 0.0
  result2 <- 1.0
  # Vector of results can have variable length although type is known
  # ahead of time
  vectorResult1 <- runif(sample(1:30, 1), 1, 10)
  vectorResult2 <- runif(sample(1:30, 1), 1, 10)

  product_result <- list(
    result1 = result1,
    result2 = result2,
    vectorResult1 = vectorResult1,
    vectorResult2 = vectorResult2
  )
  return(product_result)
})

lineprof与实际代码一起使用表明循环中列表的实例化比其他所有内容都要花费更多时间,这就是为什么我很好奇如果有办法预先分配列表的话提高速度。是否有更好的方法从分析中返回一组结果?我之所以使用列表而不是索引到data.framedata.table,是因为矢量结果的长度可变。

我知道这可能是不可能的,但我经常对StackOverflow能够提出的内容感到惊讶。我知道vectorResult1vectorResult2向量的最大长度。

系统:R 3.2.2 Windows Server Essentials 2014 64位。

更新2015-10-20 2:21 PM

我使用以下代码来评估lapply与预分配的时序差异。请随意批评我的代码和方法。这是基于其他用户决定删除的一些早期反馈:

lapply_timing <- system.time({
  replicate(50,{
      model_result <- lapply(product_names, function(product_name){
      # Do analysis here
      # The actual code takes date from a data.table and performs the analysis
      # This code is provided to illustrate what is being returned
      result1 <- 0.0
      result2 <- 1.0
      # Vector of results can have variable length although type is known
      # ahead of time
      vectorResult1 <- runif(sample(1:30, 1), 1, 10)
      vectorResult2 <- runif(sample(1:30, 1), 1, 10)

      product_result <- list(
        result1 = result1,
        result2 = result2,
        vectorResult1 = vectorResult1,
        vectorResult2 = vectorResult2
      )
      return(product_result)
    })
  })
})

lapply_timing


preallocate_timing <- system.time({
  replicate(50, {
    tst <- vector("list", length(product_names)); for (i in seq_along(tst)) tst[[i]] <- vector("list", 4)

    for(i in 1:length(product_names)){
      result1 <- 0.0
      result2 <- 1.0
      # Vector of results can have variable length although type is known
      # ahead of time
      vectorResult1 <- runif(sample(1:30, 1), 1, 10)
      vectorResult2 <- runif(sample(1:30, 1), 1, 10)

      tst[[i]][[1]] <- result1
      tst[[i]][[2]] <- result2
      tst[[i]][[3]] <- vectorResult1
      tst[[i]][[4]] <- vectorResult2
    }
  })
})

preallocate_timing

这显示两者之间的表现可以忽略不计,这让我觉得我做错了。

0 个答案:

没有答案