Самый быстрый способ чтения в 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