【问题标题】:How to batch read 2.8 GB gzipped (40 GB TSVs) files into R?如何将 2.8 GB gzipped (40 GB TSV) 文件批量读取到 R 中?
【发布时间】:2018-10-24 01:04:16
【问题描述】:

我有一个包含 31 个 gzip 压缩 TSV(2.8 GB 压缩/40 GB 未压缩)的目录。我想根据 1 列的值有条件地导入所有匹配的行,并合并到一个数据框中。

我在这里阅读了几个答案,但似乎没有一个有效 - 我怀疑它们不适合处理那么多数据。

简而言之,我该怎么做:

  1. 读取 3 GB 的 gzip 文件
  2. 仅导入其列与特定值匹配的行
  3. 将匹配的行合并到一个数据框中。

数据很整齐,只有 4 列感兴趣:日期、ip、类型(str)、类别(str)。

我尝试使用read_tsv_chunked()的第一件事:

library(purrr)
library(IPtoCountry)
library(lubridate)
library(scales)
library(plotly)
library(tidyquant)
library(tidyverse)
library(R.utils)
library(data.table)

#Generate the path to all the files.
import_path <- "import/"
files <-  import_path %>% 
  str_c(dir(import_path))

#Define a function to filter data as it comes in.
call_back <- function(x, pos){
  unique(dplyr::filter(x, .data[["type"]] == "purchase"))
}

raw_data <- files %>%
  map(~ read_tsv_chunked(., DataFrameCallback$new(call_back),
      chunk_size = 5000)) %>%
  reduce(rbind) %>%
  as_tibble() # %>%

第一种方法适用于 9 GB 的未压缩数据,但不适用于 40 GB。

第二种方法使用fread()(相同的加载包):

 #Generate the path to all the files.
    import_path <- "import/"
    files <-  import_path %>% 
      str_c(dir(import_path))

 bind_rows(map(str_c("gunzip - c", files), fread))

看起来它开始工作了,但后来被锁定了。我不知道如何在map()/str_c() 调用中将select = c(colnames) 参数传递给fread(),更不用说一列的过滤条件了。

【问题讨论】:

  • 数据是什么样的?你试过什么? (同样重要的是:您的计算机有多少内存?)请让这个问题可重现。这包括示例代码(包括列出非基础 R 包)、示例数据(例如,dput(head(x)))和预期输出。参考:stackoverflow.com/questions/5963269stackoverflow.com/help/mcvestackoverflow.com/tags/r/info
  • 它们有多少个文件(即每个文件有多大?)根据您的操作,shell 工具 (cut/grep/awk) 可能有用辅助...
  • 已添加,如果需要其他信息,请告诉我。谢谢!
  • 1) 在 fread 之后直接添加 fread 参数 - 在 map 的帮助中 ... 是传递附加参数的地方:map(str_c("gunzip - c", files), fread, select=c('mycol')) 2) 您可以尝试使用类似 map(str_c('gunzip -c ', files, '| grep "purchase"'), fread) 的命令进行过滤
  • 一个可能的解决方案是使用包 {bigreadr}(免责声明:我是作者)并调整 this vignette 来读取您的数据并将其附加到 SQLite DB。

标签: r data.table readr r-bigmemory


【解决方案1】:

这更像是一个策略答案。

R 将所有数据加载到内存中进行处理,因此您会遇到正在查看的数据量的问题。

我建议你做的,也就是我做的,是使用 Apache Spark 进行数据处理,并使用 R 包 sparklyr 与其接口。然后,您可以将数据加载到 Spark 中,在那里对其进行处理,然后将汇总的数据集检索回 R 中以进行进一步的可视化和分析。

您可以在 R Studio 实例中本地安装 Spark,并在那里做很多事情。如果您需要更多计算能力,请查看 AWS 等托管选项。

阅读此https://spark.rstudio.com/

一个技术点,有一个sparklyr 函数spark_read_text 可以将分隔的文本文件直接读取到Spark 实例中。它非常有用。

您可以从那里使用dplyr 来操作您的数据。祝你好运!

【讨论】:

    【解决方案2】:

    首先,如果使用基础 read.table,则不需要 gunzip 任何内容,因为它使用 Zlib 直接读取这些内容。如果指定了 colClasses 参数,read.table 的运行速度也会更快。

    你可能需要编写一些自定义 R 代码来直接从 31 个 TSV 中的每一个中生成一个融合数据帧,然后通过 rbinding 来累积它们。

    拥有一台具有大量快速虚拟内存的机器仍然会有所帮助。我经常按这个顺序处理数据集,有时我会发现一个 Ubuntu 系统需要内存,即使它有 32 个内核。我有一个替代系统,我让操作系统相信 SSD 是它的更多内存,给我一个有效的 64 GB RAM。我发现这对于其中一些问题非常有用。它是 Windows,所以我需要适当地设置 memory.limit(size=...)

    请注意,一旦使用 read.table 读取 TSV,它就会非常压缩,接近 gzip 提供的内容。如果你这样做,你可能不需要一个大系统。

    如果结果需要很长时间(我对此表示怀疑),请务必检查点并save.image在两者之间的位置。

    【讨论】:

    • 谢谢!以后遇到类似情况我会记住这一点的:)
    猜你喜欢
    • 2013-03-10
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-02
    • 1970-01-01
    • 2020-11-29
    • 2020-06-09
    相关资源
    最近更新 更多