如何在R中获得更好的性能:一个大文件还是几个小文件?

时间:2018-10-18 06:52:30

标签: r performance

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

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

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

我是一个初学者,所以我写的所有内容可能都没有任何意义。

这是我的代码:(之所以+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循环之前创建一个对象(巨大的文件),然后将其加载一次?

谢谢。

1 个答案:

答案 0 :(得分: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为矩阵格式,则用于创建新数据列表的这种方法看起来非常快:

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.framek <- data.table(colnames(d2), t(x), NA)