3

我有一个 33GB 的 NDJSON 文件,需要读入 R 中的 data.table。它被压缩成 2GB 的文件,理想情况下我希望将其压缩。

结构并不那么重要,除了(通过 导入时jsonlite::stream_in),我需要的数据仅在几个简单的列中。数据的绝大部分权重都保存在list我想尽快丢弃的三列内的 s 中。

我的两个挑战是:如何并行化读入,以及如何限制内存使用(现在我在这个文件上的工作人员正在使用 175GB 内存)?

我现在在做什么:

dt.x <- data.table(flatten(stream_in(gzfile("source.gz"))[, -c(5:7)]))

想法:

也许有一些方法可以忽略 NDJSON 的一部分stream_in

我可以在gzfile连接之前解析连接,例如使用正则表达式,stream_in以删除多余的数据吗?

我可以readLinesgzfile连接上执行类似操作以读取每个工作人员 100 万行的数据吗?

编辑:如果可能的话,我的目标是让其他用户可以移植并完全保留在 R 中。

4

1 回答 1

2

将 jqr 与阅读器一起使用

以下是说明如何使用 jqr 读取 gzip 压缩的 NDJSON(又名 JSONL)文件的脚本:

$ R --vanilla
> library(readr)
> library(jqr)
> read_lines("objects.json.gz") %>% jq('.a')
[
    1,
    2,
    3
]
> 

使用read_file()产生相同的结果。由于这些函数必须解压缩整个文件,因此内存需求会很大。

分别读取每个 JSON 实体

由于文件是 NDJSON,我们可以通过一次读取一个 JSON 实体来大大减少所需的 RAM 量:

con = file("objects.json", "r");
while ( length(line <- readLines(con, n = 1)) > 0) {
   print( line %>% jq('.a') );
}

jq

使用 jqr 可能有更好的方法,但如果目标是空间和时间效率,那么最好使用 jq 的命令行版本。

数数

如果您需要事先计算(解压缩的)文件中的行数,那么为了节省内存,我可能会使用system2wc如果可能的话;一切都失败了,你可以像这样运行一个片段:

n<-0;
con = file("objects.json", "r");
while (TRUE) {
   readLines(con, n = 1);
   if (length(line) == 0) { break; }
    n <- n+1;
}
于 2018-06-26T06:16:49.500 回答