【问题标题】:How to get better performance in R: one big file or several smaller files?如何在 R 中获得更好的性能:一个大文件还是几个小文件?
【发布时间】:2018-10-18 18:49:26
【问题描述】:

我有大约 200 个不同的文件(它们都是大矩阵,465x1080)(这对我来说很大)。然后我使用cbind2 将它们全部变成一个更大的矩阵(465x200000)。

我这样做是因为我需要为每一行(465 个文件)创建一个单独的文件,并且我认为 R 只需将数据从 1 个文件加载到内存一次然后每行读取一行会更容易为每个文件创建一个单独的文件,而不是为每一行打开和关闭 200 个不同的文件。

这真的是更快的方法吗? (我想知道,因为现在要花很多时间才能做到这一点)。当我从 Windows 签入任务管理器时,它显示 R 使用的 RAM,它一直从 700MB 变为 1GB 再到 700MB(每秒两次)。似乎主文件不是只加载一次,而是在每次迭代中都被加载并从内存中删除(这可能是它有点慢的原因?)。

我是初学者,所以我写的所有这些可能没有任何意义。

这是我的代码:(那些 +1 和 -1 是因为原始数据有 1 个额外的列,我在新文件中不需要)

extractStationData <- function(OriginalData, OutputName = "BCN-St") {

for (i in 1:nrow(OriginalData)) {

    OutputData <- matrix(NA,nrow = ncol(OriginalData)-1,3)
    colnames(OutputData) <- c("Time","Bikes","Slots")

    for (j in 1:(ncol(OriginalData)-1)) {

        OutputData[j,1] <- colnames(OriginalData[j+1])
        OutputData[j,2] <- OriginalData[i,j+1]

    }

    write.table(OutputData,file = paste(OutputName,i,".txt",sep = ""))
    print(i)

}

}

有什么想法吗?也许我应该在第一个 for 循环之前创建一个对象(大文件),然后只加载一次?

提前致谢。

【问题讨论】:

  • 快速思考一下:您可以通过切换到并行处理来提高性能并加快代码速度。我建议看看 foreach 和 doParallel 包。请参阅:cran.r-project.org/web/packages/doParallel/vignettes/…
  • @alex_555 他说他是初学者,你推荐的第一件事是使用并行处理?用于将文件写入磁盘?真的吗??
  • @F.Privé 你绝对是对的!我同意这对于初学者来说可能相当复杂。尽管如此,基于stackoverflow上的一些模板构建一个foreach循环可能是可行的恕我直言。与在 for 循环中寻找一些更快的函数相比,它还可能在更大程度上提高性能。
  • 布鲁诺,你只有数字数据吗?如果是这样,您可以使用包 {bigmemory} 或 {bigstatsr} 以便将矩阵的数据存储在磁盘上而不是直接存储在 RAM 中。

标签: r performance


【解决方案1】:

假设您已经创建了 465x200000 矩阵,并且只有 extractStationData 函数。然后我们可以像这样修改它:

require(data.table)
extractStationData <- function(d, OutputName = "BCN-St") {
  d2 <- d[, -1] # remove the column you do not need
  # create empty matrix outside loop:
  emtyMat <- matrix(NA, nrow = ncol(d2), 3)
  colnames(emtyMat) <- c("Time","Bikes","Slots")
  emtyMat[, 1] <- colnames(d2)
  for (i in 1:nrow(d2)) {
    OutputData <- emtyMat
    OutputData[, 2] <- d2[i, ]
    fwrite(OutputData, file = paste(OutputName, i, ".txt", sep = "")) # use fwrite for speed
  }
}

V2:

如果您的 OriginalData 是矩阵格式,那么这种创建新 data.tables 列表的方法看起来非常快:

extractStationData2 <- function(d, OutputName = "BCN-St") {
  d2 <- d[, -1] # romove the column you dont need
  ds <- split(d2, 1:nrow(d2))
  r <- lapply(ds, function(x) {
    k <- data.table(colnames(d2), x, NA)
    setnames(k, c("Time","Bikes","Slots"))
    k
  })
  r
}
dl <- extractStationData2(d) # list of new data objects
# write to files:
for (i in seq_along(dl)) {
  fwrite(dl[[i]], file = paste(OutputName, i, ".txt", sep = ""))
  }

应该也适用于data.frame,只需稍作改动: k &lt;- data.table(colnames(d2), t(x), NA)

【讨论】:

  • 感谢更好的代码!我真的离开我的电脑大约 10 个小时运行我的代码(它平均每 4 分钟创建 3 个文件)。您的代码每秒钟创建一个新文件。当我写完这篇评论时,我将拥有我需要的所有文件!
  • 顺便说一句,任务管理器说 R 现在使用 2.2GB(与以前相比是三倍/双倍),但我的笔记本电脑有足够的 RAM,所以这不是问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-09
  • 2020-02-24
  • 2013-02-09
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多