Самый быстрый способ чтения в 100 000 файлов .dat.gz

У меня есть несколько сотен тысяч очень маленьких файлов .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))    
}

И здесь применяется код:

# 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))

И вот мой самый эффективный код до сих пор читал в данных:

# 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

Я запустил это в функцию и применил ее параллельно, но для меня это слишком много слишком медленно.

Я уже пробовал h2o.importFolder из замечательного пакета h2o, но на самом деле он намного медленнее, чем обычный R с data.table. Возможно, есть способ ускорить рассылку файлов, но я не уверен. Из нескольких раз, когда я запускал это, я заметил, что распаковка файлов обычно занимает около 2/3 времени функции.

Ответ 1

Я удивлен, что это действительно сработало. Надеюсь, это сработает для вашего дела. Мне очень любопытно узнать, как скорость сравнивается с чтением сжатых данных с диска непосредственно из 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

Ответ 2

R имеет возможность считывать gzipped файлы изначально, используя функцию gzfile. Посмотрите, работает ли это.

rbindlist(lapply(dat.files, function(f) {
    read.delim(gzfile(f))
}))

Ответ 3

Узкое место может быть вызвано использованием вызова system() во внешнее приложение.

Вы должны попробовать использовать функции builting для извлечения архива. Этот ответ объясняет, как: Декомпрессировать gz файл с помощью R