当"跳过"时,fread会占用一小部分内存。很大

时间:2018-01-02 18:27:55

标签: r csv data.table

我有一个大的csv文件(20G,差不多2亿行),我无法将其作为一个整体加载到内存中---->所以我想逐件加载它。

我没有找到在fread中使用文件连接的方法(就像在readLines中一样)---->所以我尝试使用"跳过":

for(i in 1:100){
lines=fread(filename,nrows=rowPerRead,skip=(i-1)*rowPerRead)
}

这在开始时工作正常。但随着跳跃越来越大 - 以非线性方式变得越来越慢。事实证明,尽管这些行被跳过,但在此过程中仍然需要大量内存,并且只有在完成该过程时才会被清除。一旦内存耗尽,进程就会变得非常慢。

> system.time({newLines=fread("userinfo4.csv",nrows=1e6,skip=1,quote="") })
   user  system elapsed 
   0.71    0.04    0.73 
> system.time({newLines=fread("userinfo4.csv",nrows=1e6,skip=1e8,quote="") })
Read 1000000 rows and 12 (of 12) columns from 20.049 GB file in 00:01:47
   user  system elapsed 
  21.89   13.76  106.60 
> system.time({newLines=fread("userinfo4.csv",nrows=1e6,skip=1.4e8,quote="") })
Read 1000000 rows and 12 (of 12) columns from 20.049 GB file in 00:02:48
   user  system elapsed 
  16.95   12.49  169.76 
> 

第二次和第三次运行的内存使用情况。 enter image description here

所以我的问题是: 1.使用大型跳过运行fread是否有更高效的内存方式? 2.有没有办法从文件连接运行fread ---所以我可以从上次读取继续而不是从头开始重新启动。

2 个答案:

答案 0 :(得分:1)

您可以使用fread的功能来接受预处理文件作为输入的shell命令。使用此选项,我们可以运行gawk脚本来提取所需的行。注意,如果你的系统上已经没有gawk了,你可能需要安装gawk(Linux和类似Unix的机器通常已经安装了它,在Windows上你可能需要安装它)。

n = 100   # lines to skip
cmd = paste0('gawk "NR > ', n, '" ', filename)
lines = fread(cmd, nrows = rowPerRead)

答案 1 :(得分:0)

我在使用data.table::fread在跳过行时以大块形式读取数据时遇到了相同的问题。以我的经验,添加一个garbage collection步骤可以解决此问题。 (尽管R应该在需要内存时自动调用base::gc(),但出于某种原因在循环中使用了data.table::fread,它似乎无法有效工作。)

在您的示例代码中,它看起来像这样:

for(i in 1:100){
lines=fread(filename,nrows=rowPerRead,skip=(i-1)*rowPerRead)
gc()
}