2016-03-03 5 views
12

Ich habe ein paar hunderttausend sehr kleine .dat.gz Dateien, die ich in R möglichst effizient einlesen möchte. Ich lese die Datei ein und aggregiere und verwerfe die Daten sofort. Daher mache ich mir keine Sorgen über die Speicherverwaltung, wenn ich am Ende des Prozesses angelangt bin. Ich möchte den Engpass, der beim Entpacken und Einlesen der Daten passiert, wirklich beschleunigen.Schnellste Möglichkeit zum Einlesen von 100.000 .dat.gz Dateien

Jeder Datensatz besteht aus 366 Zeilen und 17 Spalten. Hier ist ein reproduzierbares Beispiel dafür, was ich bisher tue:

Gebäude reproduzierbare Daten:

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

Und hier ist der Code der Anwendung:

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

Und hier ist mein effizientesten Code so weit Zum Einlesen der Daten:

Ich habe dies in einer Funktion abgefüllt und in Par. angewendet Allel, aber es ist immer noch viel viel zu langsam für das, wofür ich das brauche.

Ich habe bereits versucht, die h2o.importFolder vom wunderschönen h2o Paket, aber es ist eigentlich viel viel langsamer im Vergleich zu einfachen R mit data.table verwenden. Vielleicht gibt es eine Möglichkeit, das Entpacken von Dateien zu beschleunigen, aber ich bin unsicher. Von den wenigen Malen, die ich ausgeführt habe, habe ich bemerkt, dass das Entpacken der Dateien normalerweise ungefähr 2/3 der Funktionszeit dauert.

+0

Ich bekomme verbesserte Geschwindigkeiten (im Vergleich zu Ihrem bisher effizientesten Code), indem Sie 'read_tsv' aus dem" readr "-Paket verwenden. 'rbindlist (lapply (dat.files, read_tsv))' – A5C1D2H2I1M1N2O1R2T1

Antwort

11

Ich bin irgendwie überrascht, dass dies tatsächlich funktioniert hat. Hoffentlich funktioniert es für Ihren Fall. Ich bin ziemlich neugierig zu wissen, wie schnell sich komprimierte Daten von der Festplatte direkt aus R lesen lassen (wenn auch mit einer Strafe für Nicht-Vektorisierung).

+2

Überrascht auch. Das ist großartig. Irgendeine Idee, wie gut es in Bezug auf die Geschwindigkeit mit den anderen Methoden vergleicht? – Arun

+0

Ich habe gerade die Antwort bearbeitet. Fragen Sie sich auch, wie das OP hat eine ausgezeichnete Testumgebung ... –

+2

Große Antwort! Mit dieser Methode konnte ich meine Daten wesentlich schneller lesen und aggregieren. Mit Hilfe von 8 Cores konnte ich 696.000 Dateien in 1,5 Minuten einlesen und verarbeiten, wobei vorher 12 Minuten vergangen sind. Ich muss das als nächstes auf Millionen von Dateien skalieren, also ist das eine große Hilfe! Kann ich fragen, was der 'grep -v"^Day "' Teil des Codes tut? –

4

Der Flaschenhals kann durch die Verwendung des system() -Aufrufs an eine externe Anwendung verursacht werden.

Sie sollten versuchen, mit den Building-Funktionen das Archiv zu extrahieren. Diese Antwort erklärt, wie: Decompress gz file using R

6

R hat die Fähigkeit, gziped Dateien nativ zu lesen, mit der Funktion. Sehen Sie, ob das funktioniert.

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

Sie können dies auf 'rbindlist (lapply (dat.files, read.delim))' vereinfachen. +1. Dies scheint auch schneller als 'read_tsv' zu sein. – A5C1D2H2I1M1N2O1R2T1

+0

Das hat ziemlich geholfen. Ich bin jetzt in der Lage, 232.000 Dateien in 12 Minuten statt 18 zu lesen. Ich brauche das noch ein bisschen schneller, aber das ist ein guter Anfang –