阅读100,000 .dat.gz文件的最快方式

Mik*_*han 12 performance r data.table h2o

我有几十万个非常小的.dat.gz文件,我想以最有效的方式读入R.我在文件中读取然后立即聚合并丢弃数据,因此我不担心在接近流程结束时管理内存.我只是想加快瓶颈,这恰好是解压缩和读取数据.

每个数据集由366行和17列组成.这是我目前所做的可重复的例子:

构建可重现的数据:

require(data.table)

# Make dir
system("mkdir practice")

# Function to create data
create_write_data <- function(file.nm) {
  dt <- data.table(Day=0:365)
  dt[, (paste0("V", 1:17)) := lapply(1:17, function(x) rnorm(n=366))]
  write.table(dt, paste0("./practice/",file.nm), row.names=FALSE, sep="\t", quote=FALSE)
  system(paste0("gzip ./practice/", file.nm))    
}
Run Code Online (Sandbox Code Playgroud)

以下是代码申请:

# Apply function to create 10 fake zipped data.frames (550 kb on disk)
tmp <- lapply(paste0("dt", 1:10,".dat"), function(x) create_write_data(x))
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是我最有效的代码来读取数据:

# Function to read in files as fast as possible
read_Fast <- function(path.gz) {
  system(paste0("gzip -d ", path.gz)) # Unzip file
  path.dat <- gsub(".gz", "", path.gz)
  dat_run <- fread(path.dat)
}

# Apply above function
dat.files <- list.files(path="./practice", full.names = TRUE)
system.time(dat.list <- rbindlist(lapply(dat.files, read_Fast), fill=TRUE))
dat.list
Run Code Online (Sandbox Code Playgroud)

我已将其装入一个函数中并将其并行应用,但对于我需要的内容来说,它仍然太慢了.

我已经尝试了h2o.importFolder从美妙的h2o包,但它是相对于使用普通实际上非常非常慢Rdata.table.也许有办法加快文件的解压缩,但我不确定.从我运行的几次开始,我注意到解压缩文件通常需要大约2/3的函数时间.

Cla*_*ley 11

我有点惊讶这实际上是有效的.希望它适用于您的情况.我很想知道速度与从R直接从磁盘读取压缩数据的速度如何相反(尽管非矢量化会受到惩罚).

tblNames = fread('cat *dat.gz | gunzip | head -n 1')[, colnames(.SD)]
tbl = fread('cat *dat.gz | gunzip | grep -v "^Day"')
setnames(tbl, tblNames)
tbl
Run Code Online (Sandbox Code Playgroud)

  • 也很惊讶.这真太了不起了.知道它在速度方面与其他方法相比有多好吗? (2认同)
  • 很棒的答案!使用这种方法,我能够更快地读取和聚合我的数据.使用8个核心,我能够在1.5分钟内读入并处理696,000个文件,之前需要12分钟.我接下来需要将其扩展到数百万个文件,所以这是一个巨大的帮助!我可以问一下代码中的'grep -v"^ Day"部分是什么吗? (2认同)

Hon*_*Ooi 6

R能够使用该gzfile函数本机读取gzip文件.看看这是否有效.

rbindlist(lapply(dat.files, function(f) {
    read.delim(gzfile(f))
}))
Run Code Online (Sandbox Code Playgroud)