12

我想知道使用 data.table fread 函数可以读取的行数是否有限制。我正在处理一个有 40 亿行、4 列、大约 40 GB 的表。看起来 fread 只会读取前 8.4 亿行。它没有给出任何错误,而是返回到 R 提示符,就好像它已经读取了所有数据一样!

我知道 fread 目前不适合“产品使用”,并且想了解是否有任何时间框架来实施产品发布。

我使用 data.table 的原因是,对于这种大小的文件,与将文件加载到 data.frame 等相比,它在处理数据方面非常有效。

目前,我正在尝试其他 2 种选择 -

1)使用扫描并传递给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 拆分 5 亿行并按顺序读取它们……然后将文件按顺序循环到 fread - 有点麻烦,但似乎是唯一可行的解​​决方案。

我认为可能有一种 Rcpp 方法可以更快地做到这一点,但我不确定它是如何实现的。

提前致谢。

4

1 回答 1

8

我能够使用 Stackoverflow 上另一个帖子的反馈来完成此操作。这个过程非常快,使用 fread 迭代在大约 10 分钟内读取了 40 GB 的数据。Foreach-dopar 在单独运行以将文件顺序读取到新的 data.tables 时无法工作,因为下面页面中也提到了一些限制。

注意:文件列表(file_map)是通过简单地运行来准备的——

file_map <- list.files(pattern="test.$")  # Replace pattern to suit your requirement

mclapply 与大对象 - “序列化太大而无法存储在原始向量中”

引用——

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 而不会遇到“序列化太大错误”。

另一个有用的帖子是——并行加载文件不使用 foreach + data.table

于 2013-07-12T14:25:46.547 回答