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