在R中导入数百万个文件的最快方法?

ste*_*hom 8 csv import r

我有1500万个CSV文件,每个文件有两列(整数和浮点数),以及5到500行.每个文件看起来像:

3453,0.034
31,0.031
567,0.456
...
Run Code Online (Sandbox Code Playgroud)

目前,我正在迭代所有文件,并使用read.csv()将每个文件导入大列表.这是一个简化版本:

allFileNames = Sys.glob(sprintf("%s/*/*/results/*/*", dir))

s$scores = list()

for (i in 1:length(allFileNames)){
        if ((i %% 1000) == 0){
            cat(sprintf("%d of %d\n", i, length(allFileNames)))
        }

        fileName = allFileNames[i]
        approachID = getApproachID(fileName) 
        bugID = getBugID(fileName)

        size = file.info(fileName)$size
        if (!is.na(size) && size > 0){ # make sure file exists and is not empty
            tmp = read.csv(fileName, header=F, colClasses=c("integer", "numeric"))
            colnames(tmp) = c("fileCode", "score")
            s$scores[[approachID]][[bugID]]  = tmp
        } else {
            # File does not exist, or is empty. 
            s$scores[[approachID]][[bugID]] = matrix(-1, ncol=2, nrow=1)
        }
    }

tmp = read.csv(fileName, header=F, colClasses=c("integer", "numeric")
Run Code Online (Sandbox Code Playgroud)

稍后在我的代码中,我将回顾列表中的每个矩阵,并计算一些指标.

启动此导入过程后,看起来需要3到5天才能完成.有更快的方法吗?

编辑:我添加了有关我的代码的更多详细信息.

Jef*_*len 7

我不清楚你的目标,但如果你试图将所有这些文件读入一个R数据结构,那么我会看到两个主要的性能问题:

  1. 文件访问时间 - 从您请求read.csv的那一刻起,在您的机器上启动了无数复杂的进程,包括查看该文件是否存在,在内存或磁盘上查找该文件的位置(如果需要,将数据读入内存) be),然后解释R中的数据.当你读入数百万个文件时,我预计这将是一个几乎不变的减速.
  2. 在读取每个新文件的情况下增加单个数据结构.每次要向矩阵添加几行时,您可能需要重新分配类似大小的内存块才能存储更大的矩阵.如果你的阵列增长了1500万次,你肯定会注意到这里的性能下降.有了这个问题,随着您在更多文件中的读取,性能将逐渐变差.

所以做一些快速分析,看看读取的时间.如果他们在阅读更多文件时逐渐放慢速度,那么让我们关注问题#2.如果它一直很慢,那么让我们担心问题#1.

关于解决方案,我想你可以从两件事开始:

  1. 将CSV文件与另一种编程语言结合使用.如果您只是循环遍历文件并将它们连接成一个大文件,那么简单的shell脚本可能会为您完成这项工作.正如Joshua和Richie在下面提到的那样,您可以通过使用更高效scan()readlines()功能来优化它而不必偏离另一种语言.
  2. 预先统一您的统一数据结构.例如,如果您正在使用矩阵,请将行数设置为~1,500万x 100.这将确保您只需要为此对象在内存中找到一次空间,其余操作将只插入数据进入预先确定的矩阵.

添加一些代码的更多细节(列表看起来像你正在使用的那些?),我们可能会更有帮助.

  • 另请注意,`scan`比`read.csv`更合适,因为数据都可以存储为数字. (3认同)

Mar*_*rek 6

使用scan(作为评论中的Joshua状态)可能更快(3-4次):

scan(fileName, what=list(0L,0.0), sep=",", dec=".", quiet=TRUE)
Run Code Online (Sandbox Code Playgroud)

主要区别在于scan返回列表包含两个元素并read.csv返回data.frame.