在R中使用fread函数的data.table的行限制

12

我想知道使用data.table fread函数读取行数是否有限制。我的表格有40GB,4亿行,4列。看起来fread只会读取前大约8.4亿行。它没有报错,但是返回到R提示符,就好像已经读取了所有的数据一样!

我知道fread目前不适用于"prod use",我想知道是否有任何时间框架来实现生产版本。

我使用data.table的原因是,在处理这样大小的文件时,与加载数据框等相比,它非常高效。

目前,我正在尝试另外两种选择 -

1)使用scan并传递给data.table

data.table(matrix(scan("file.csv",what="integer",sep=","),ncol=4))

Resulted in --
Error in scan(file, what, nmax, sep, dec, quote, skip, nlines, na.strings,  :
  too many items

2)使用Unix的split将文件分割成多个单独的段,每段限制为大约5亿行,然后按顺序逐个读取它们... 然后循环顺序地进入fread - 有点麻烦,但似乎是唯一可行的解决方案。

我认为可能有一种更快速的Rcpp方法来实现这一点,但不确定通常如何实现。

提前致谢。


1
请确保您的文件中最后读取的一行或其后面的行没有任何异常,然后提交错误报告或联系软件包维护者。 - Roland
你确定你有足够的RAM吗?并且你是否在使用64位的R? - eddi
不,使用Rcpp并不一定有更快的方法,因为Matt已经使用了mmap。请检查您的操作系统文档以获取mmap调用限制。十亿级数据可能会超出极限... - Dirk Eddelbuettel
1
关于更快读取文件的方法,根据我的经验,使用原生KDB+(kx.com)可以在几分钟内完成此类任务。据我所知,由于KDB+是用C编写的,因此我一直在想我们是否能够在R中实现相同的速度... KDB+还使用了一些超级优化的代码(整个数据库二进制文件只有1兆!),并且也使用了mmap技术来映射文件。虽然有点离题,但仍然很有趣。 - xbsd
1
@CauchyDistributedRV:R before 3.0.0版本的限制是2^31 - 1;后来通过使用双精度索引进行切换,R 3.0.0版本解除了这一限制。请参阅NEWS文件以获取更多信息,但据我回忆,现在的限制是2^35 - 1。话虽如此,您的观点仍然是正确的。 - Dirk Eddelbuettel
显示剩余4条评论
1个回答

8
我使用了Stackoverflow上的另一篇帖子中的反馈来完成此操作。使用fread进行迭代,过程非常快,大约10分钟读取了40GB的数据量。由于某些限制,无法仅使用foreach-dopar自行按顺序将文件读入新的data.table中,这也在下面的页面上提到。
注意:文件列表(file_map)是通过简单地运行以下内容准备的--
file_map <- list.files(pattern="test.$")  # Replace pattern to suit your requirement

mclapply 使用大型对象时出现 "serialization is too large to store in a raw vector" 的错误提示

引用 --

collector = vector("list", length(file_map)) # more complex than normal for speed 

for(index in 1:length(file_map)) {
reduced_set <- mclapply(file_map[[index]], function(x) {
  on.exit(message(sprintf("Completed: %s", x)))
  message(sprintf("Started: '%s'", x))
  fread(x)             # <----- CHANGED THIS LINE to fread
}, mc.cores=10)
collector[[index]]= reduced_set

}

# Additional line (in place of rbind as in the URL above)

for (i in 1:length(collector)) { rbindlist(list(finalList,yourFunction(collector[[i]][[1]]))) }
# Replace yourFunction as needed, in my case it was an operation I performed on each segment and joined them with rbindlist at the end.

我的函数包含一个循环,使用Foreach dopar在file_map中指定的多个核心上执行每个文件。当在组合文件上运行时,这允许我使用dopar而不遇到“序列化过大”的错误。
另一个有用的帖子在此处 - loading files in parallel not working with foreach + data.table

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接