【发布时间】:2018-10-24 01:04:16
【问题描述】:
我有一个包含 31 个 gzip 压缩 TSV(2.8 GB 压缩/40 GB 未压缩)的目录。我想根据 1 列的值有条件地导入所有匹配的行,并合并到一个数据框中。
我在这里阅读了几个答案,但似乎没有一个有效 - 我怀疑它们不适合处理那么多数据。
简而言之,我该怎么做:
- 读取 3 GB 的 gzip 文件
- 仅导入其列与特定值匹配的行
- 将匹配的行合并到一个数据框中。
数据很整齐,只有 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/5963269、stackoverflow.com/help/mcve 和 stackoverflow.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