在R中快速读取非常大的表格作为数据框

我有非常大的表(3000万行),我想在R中加载一个数据read.table()有很多方便的功能,但是看起来好像有很多逻辑在执行时会减慢事情下降。 就我而言,我假设我提前知道列的类型,该表不包含任何列标题或行名称,并且没有任何我必须担心的病态字符。

我知道使用scan()作为列表在表中读取可能非常快,例如:

datalist <- scan('myfile',sep='t',list(url='',popularity=0,mintime=0,maxtime=0)))

但是,我的一些尝试将其转换为数据帧似乎将上述性能降低了6倍:

df <- as.data.frame(scan('myfile',sep='t',list(url='',popularity=0,mintime=0,maxtime=0))))

有没有更好的方法来做到这一点? 或者可能完全不同的方法来解决这个问题?


数年后的更新

这个答案是旧的,R已经开始了。 调整read.table以更快运行会带来宝贵的好处。 您的选择是:

  • data.table使用fread将csv /制表符分隔文件中的数据直接导入R.请参阅mnel的答案。

  • 使用read_tablereadr (从2015年4月在CRAN)。 这很像上面的fread 。 链接中的readme解释了两个函数之间的区别( readr目前声称比data.table::freaddata.table::fread )。

  • read.csv.rawiotools提供了快速读取CSV文件第三个选项。

  • 试图在数据库中存储尽可能多的数据而不是平面文件。 (除了作为一个更好的永久存储介质,数据被传递到和来自R以二进制格式,这是更快。) read.csv.sqlsqldf包,如在JD龙的回答那样,进口数据到临时SQLite数据库,然后将其读入R.另请参阅: RODBC软件包,反向取决于DBI软件包页的部分。 MonetDB.R为您提供了一种假装为数据框的数据类型,但实际上是MonetDB,提高了性能。 用monetdb.read.csv函数导入数据。 dplyr允许您直接处理存储在多种类型的数据库中的数据。

  • 以二进制格式存储数据对于提高性能也很有用。 使用saveRDS / readRDS (见下文),该h5rhdf5包HDF5格式,或write_fst / read_fstfst包。


  • 原来的答案

    无论使用read.table还是scan,都有几件简单的事情可以尝试。

  • 设置nrows =数据中的记录数( scan nmax )。

  • 确保comment.char=""关闭评论的解释。

  • read.table使用colClasses显式定义每个列的类。

  • 设置multi.line=FALSE也可以提高扫描的性能。

  • 如果这些东西都不起作用,那么使用其中一个分析包来确定哪些线路正在放慢速度。 也许你可以根据结果编写一个read.table的简化版本。

    另一种方法是在将数据读入R之前过滤数据。

    或者,如果问题是您必须定期读取它,则使用这些方法一次读取数据,然后使用save saveRDS将数据帧保存为二进制blob,然后下次load读取速度更快readRDS


    这是一个利用data.table 1.8.7中的fread的例子

    这些例子来自于帮助页fread ,对我的Windows XP的Core 2 Duo E8400的时机。

    library(data.table)
    # Demo speedup
    n=1e6
    DT = data.table( a=sample(1:1000,n,replace=TRUE),
                     b=sample(1:1000,n,replace=TRUE),
                     c=rnorm(n),
                     d=sample(c("foo","bar","baz","qux","quux"),n,replace=TRUE),
                     e=rnorm(n),
                     f=sample(1:1000,n,replace=TRUE) )
    DT[2,b:=NA_integer_]
    DT[4,c:=NA_real_]
    DT[3,d:=NA_character_]
    DT[5,d:=""]
    DT[2,e:=+Inf]
    DT[3,e:=-Inf]
    

    标准的read.table

    write.table(DT,"test.csv",sep=",",row.names=FALSE,quote=FALSE)
    cat("File size (MB):",round(file.info("test.csv")$size/1024^2),"n")    
    ## File size (MB): 51 
    
    system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
    ##    user  system elapsed 
    ##   24.71    0.15   25.42
    # second run will be faster
    system.time(DF1 <- read.csv("test.csv",stringsAsFactors=FALSE))        
    ##    user  system elapsed 
    ##   17.85    0.07   17.98
    

    优化的read.table

    system.time(DF2 <- read.table("test.csv",header=TRUE,sep=",",quote="",  
                              stringsAsFactors=FALSE,comment.char="",nrows=n,                   
                              colClasses=c("integer","integer","numeric",                        
                                           "character","numeric","integer")))
    
    
    ##    user  system elapsed 
    ##   10.20    0.03   10.32
    

    FREAD

    require(data.table)
    system.time(DT <- fread("test.csv"))                                  
     ##    user  system elapsed 
    ##    3.12    0.01    3.22
    

    sqldf

    require(sqldf)
    
    system.time(SQLDF <- read.csv.sql("test.csv",dbname=NULL))             
    
    ##    user  system elapsed 
    ##   12.49    0.09   12.69
    
    # sqldf as on SO
    
    f <- file("test.csv")
    system.time(SQLf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))
    
    ##    user  system elapsed 
    ##   10.21    0.47   10.73
    

    ff / ffdf

     require(ff)
    
     system.time(FFDF <- read.csv.ffdf(file="test.csv",nrows=n))   
     ##    user  system elapsed 
     ##   10.85    0.10   10.99
    

    综上所述:

    ##    user  system elapsed  Method
    ##   24.71    0.15   25.42  read.csv (first time)
    ##   17.85    0.07   17.98  read.csv (second time)
    ##   10.20    0.03   10.32  Optimized read.table
    ##    3.12    0.01    3.22  fread
    ##   12.49    0.09   12.69  sqldf
    ##   10.21    0.47   10.73  sqldf on SO
    ##   10.85    0.10   10.99  ffdf
    

    我最初没有看到这个问题,并在几天后问了一个类似的问题。 我将把我以前的问题解决,但我想我会在这里添加一个答案来解释我如何使用sqldf()来执行此操作。

    关于将2GB或更多文本数据导入到R数据框的最佳方法,我们已经讨论过很少。 昨天我写了一篇关于使用sqldf()将数据作为暂存区导入SQLite的博客文章,然后将它从SQLite中吸收到R中。这对我来说非常有用。 我能够在<5分钟内获得2GB(3列,40mm行)的数据。 相比之下, read.csv命令整夜运行并且从未完成。

    这是我的测试代码:

    设置测试数据:

    bigdf <- data.frame(dim=sample(letters, replace=T, 4e7), fact1=rnorm(4e7), fact2=rnorm(4e7, 20, 50))
    write.csv(bigdf, 'bigdf.csv', quote = F)
    

    在运行以下导入例程之前,我重新启动了R:

    library(sqldf)
    f <- file("bigdf.csv")
    system.time(bigdf <- sqldf("select * from f", dbname = tempfile(), file.format = list(header = T, row.names = F)))
    

    我让下面一行运行整夜,但它从未完成:

    system.time(big.df <- read.csv('bigdf.csv'))
    
    链接地址: http://www.djcxy.com/p/30825.html

    上一篇: Quickly reading very large tables as dataframes in R

    下一篇: R inconsistency: why add=T sometimes works and sometimes not in the plot() function?