Ich habe sehr große Tabellen (30 Millionen Zeilen), die ich als Datenrahmen in R laden möchte. Es read.table()
hat viele praktische Funktionen, aber es scheint, dass die Implementierung viel Logik enthält, die die Dinge verlangsamen würde. In meinem Fall gehe ich davon aus, dass ich die Spaltentypen im Voraus kenne, die Tabelle keine Spaltenüberschriften oder Zeilennamen enthält und keine pathologischen Zeichen enthält, über die ich mir Sorgen machen muss.
Ich weiß, dass das Lesen einer Tabelle als Liste mit scan()
sehr schnell sein kann, z.
datalist <- scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0)))
Einige meiner Versuche, dies in einen Datenrahmen umzuwandeln, scheinen jedoch die Leistung des oben genannten um den Faktor 6 zu verringern:
df <- as.data.frame(scan('myfile',sep='\t',list(url='',popularity=0,mintime=0,maxtime=0))))
Gibt es einen besseren Weg, dies zu tun? Oder ganz andere Herangehensweise an das Problem?
feather
. Das Lesen von Datenfeather
ist viel schneller alsfread
. Zum Beispiel war ein 4-GB-Datensatz, den ich gerade geladen habe,read_feather
ungefähr 4,5-mal schneller alsfread
. Das Speichern von Datenfwrite
ist noch schneller. blog.dominodatalab.com/the-r-data-io-shootoutfeather
also schneller zum Lesen, verbraucht aber viel mehr Speicherplatz.feather
ist dies eine gute Option. Wenn Sie nur daran interessiert sind, Ihre Daten in R lesen zu können,rds
ist dies vorzuziehen.Hier ist ein Beispiel, das
fread
von verwendetdata.table
1.8.7Die Beispiele stammen von der
fread
Hilfeseite zu , mit den Timings auf meinem Windows XP Core 2 Duo E8400.Standard-Lesetabelle
optimierte read.table
fread
sqldf
ff / ffdf
Zusammenfassend:
quelle
fread
. Hatte versucht, es mit den Basis-R-Funktionen einzulesen, und es dauerte ungefähr 15 Stunden.readr
?fread
einige echte Konkurrenten jetzt hat, könnte nützlich sein , Benchmarks hinzufügen für eine optimiertefread
Nutzung - AngabecolClasses
usw.Ich habe diese Frage anfangs nicht gesehen und einige Tage später eine ähnliche Frage gestellt. Ich werde meine vorherige Frage aufschreiben, aber ich dachte, ich würde hier eine Antwort hinzufügen, um zu erklären, wie ich das früher gemacht
sqldf()
habe.Es wurde wenig darüber diskutiert, wie 2 GB oder mehr Textdaten am besten in einen R-Datenrahmen importiert werden können. Gestern habe ich einen Blog-Beitrag geschrieben, in dem es darum geht
sqldf()
, die Daten als Staging-Bereich in SQLite zu importieren und sie dann von SQLite in R zu übernehmen. Das funktioniert sehr gut für mich. Ich konnte 2 GB (3 Spalten, 40 mm Zeilen) Daten in <5 Minuten abrufen. Im Gegensatz dazu lief derread.csv
Befehl die ganze Nacht und wurde nie ausgeführt.Hier ist mein Testcode:
Richten Sie die Testdaten ein:
Ich habe R neu gestartet, bevor ich die folgende Importroutine ausgeführt habe:
Ich habe die folgende Zeile die ganze Nacht laufen lassen, aber sie wurde nie abgeschlossen:
quelle
Seltsamerweise hat jahrelang niemand den unteren Teil der Frage beantwortet, obwohl dies ein wichtiger Teil ist -
data.frame
es handelt sich lediglich um Listen mit den richtigen Attributen. Wenn Sie also große Datenmengen haben, möchten Sie diese nichtas.data.frame
für eine Liste verwenden oder ähnliches. Es ist viel schneller, eine Liste einfach in einen Datenrahmen zu "verwandeln":Dadurch wird keine Kopie der Daten erstellt, sodass diese sofort verfügbar sind (im Gegensatz zu allen anderen Methoden). Es wird davon ausgegangen, dass Sie bereits eingestellt haben
names()
die Liste bereits entsprechend festgelegt haben.[Was das Laden großer Datenmengen in R
readBin()
betrifft - ich persönlich speichere sie spaltenweise in Binärdateien und verwende sie -, ist dies bei weitem die schnellste Methode (außer Mapping) und wird nur durch die Festplattengeschwindigkeit begrenzt. Das Parsen von ASCII-Dateien ist im Vergleich zu Binärdaten von Natur aus langsam (auch in C).]quelle
tracmem
schlägt dies vorattr<-
und erstelltclass<-
intern Kopien.bit::setattr
oderdata.table::setattr
nicht.df=scan(...); names(df)=...; attr...; class...
- siehetracemem()
(getestet in R 2.15.2)Dies wurde zuvor in der R-Hilfe gefragt , daher lohnt es sich, dies zu überprüfen.
Ein Vorschlag war,
readChar()
das Ergebnis mitstrsplit()
und zu verwenden und dann zu manipulierensubstr()
. Sie können sehen, dass die Logik von readChar viel geringer ist als die von read.table.Ich weiß nicht, ob Speicher ein Problem ist, aber vielleicht möchten Sie auch einen Blick auf das HadoopStreaming- Paket werfen . Hierbei wird Hadoop verwendet , ein MapReduce-Framework, das für den Umgang mit großen Datenmengen entwickelt wurde. Dazu würden Sie die Funktion hsTableReader verwenden. Dies ist ein Beispiel (aber es hat eine Lernkurve, um Hadoop zu lernen):
Die Grundidee hier ist, den Datenimport in Blöcke aufzuteilen. Sie könnten sogar so weit gehen, eines der parallelen Frameworks (z. B. Schnee) zu verwenden und den Datenimport parallel durchzuführen, indem Sie die Datei segmentieren. Höchstwahrscheinlich jedoch für große Datenmengen, die nicht helfen, da Sie auf Speicherbeschränkungen stoßen. Aus diesem Grund ist das Reduzieren von Karten ein besserer Ansatz.
quelle
Eine Alternative ist die Verwendung des
vroom
Pakets. Jetzt auf CRAN.vroom
Lädt nicht die gesamte Datei, sondern indiziert, wo sich die einzelnen Datensätze befinden, und wird später gelesen, wenn Sie sie verwenden.Siehe Einführung in vroom , Erste Schritte mit vroom und den vroom-Benchmarks .
Die grundlegende Übersicht ist, dass das anfängliche Lesen einer großen Datei viel schneller ist und nachfolgende Änderungen an den Daten möglicherweise etwas langsamer sind. Je nachdem, was Sie verwenden, ist dies möglicherweise die beste Option.
Sehen Sie sich unten ein vereinfachtes Beispiel aus den vroom-Benchmarks an . Die wichtigsten Teile sind die superschnellen Lesezeiten, aber leicht säende Vorgänge wie Aggregate usw.
quelle
Ein kleiner zusätzlicher erwähnenswerter Punkt. Wenn Sie eine sehr große Datei haben, können Sie die Anzahl der Zeilen (wenn kein Header vorhanden ist) im laufenden Betrieb berechnen (wobei
bedGraph
sich der Name Ihrer Datei in Ihrem Arbeitsverzeichnis befindet):Sie können das dann entweder in
read.csv
,read.table
...quelle
Oft denke ich, dass es nur eine gute Praxis ist, größere Datenbanken in einer Datenbank zu halten (z. B. Postgres). Ich benutze nichts zu viel Größeres als (nrow * ncol) ncell = 10M, was ziemlich klein ist; Ich stelle jedoch häufig fest, dass R nur dann speicherintensive Diagramme erstellen und speichern soll, wenn ich aus mehreren Datenbanken abfrage. In der Zukunft von 32-GB-Laptops werden einige dieser Arten von Speicherproblemen verschwinden. Der Reiz, eine Datenbank zum Speichern der Daten zu verwenden und dann den Speicher von R für die resultierenden Abfrageergebnisse und Diagramme zu verwenden, kann dennoch nützlich sein. Einige Vorteile sind:
(1) Die Daten bleiben in Ihrer Datenbank geladen. Sie stellen in pgadmin einfach wieder eine Verbindung zu den gewünschten Datenbanken her, wenn Sie Ihren Laptop wieder einschalten.
(2) Es ist wahr, dass R viel mehr raffinierte statistische und grafische Operationen ausführen kann als SQL. Ich denke jedoch, dass SQL besser dafür ausgelegt ist, große Datenmengen abzufragen als R.
quelle
Ich lese Daten sehr schnell mit dem neuen
arrow
Paket. Es scheint in einem ziemlich frühen Stadium zu sein.Insbesondere verwende ich das Parkett- Säulenformat. Dies konvertiert zurück zu a
data.frame
in R , aber Sie können noch tiefere Beschleunigungen erzielen, wenn Sie dies nicht tun. Dieses Format ist praktisch, da es auch von Python aus verwendet werden kann.Mein Hauptanwendungsfall hierfür ist ein ziemlich zurückhaltender RShiny-Server. Aus diesen Gründen ziehe ich es vor, Daten an die Apps anzuhängen (dh außerhalb von SQL), und benötige daher eine geringe Dateigröße sowie Geschwindigkeit.
Dieser verlinkte Artikel bietet Benchmarking und einen guten Überblick. Ich habe unten einige interessante Punkte zitiert.
https://ursalabs.org/blog/2019-10-columnar-perf/
Dateigröße
Lesegeschwindigkeit
Unabhängiger Test
Ich habe ein unabhängiges Benchmarking für einen simulierten Datensatz von 1.000.000 Zeilen durchgeführt. Grundsätzlich habe ich ein paar Dinge durcheinander gebracht, um die Komprimierung herauszufordern. Außerdem habe ich ein kurzes Textfeld mit zufälligen Wörtern und zwei simulierten Faktoren hinzugefügt.
Daten
Lesen und Schreiben
Das Schreiben der Daten ist einfach.
Das Lesen der Daten ist ebenfalls einfach.
Ich habe das Lesen dieser Daten anhand einiger konkurrierender Optionen getestet und dabei etwas andere Ergebnisse erzielt als mit dem obigen Artikel, der erwartet wird.
Diese Datei ist bei weitem nicht so groß wie der Benchmark-Artikel. Vielleicht ist das der Unterschied.
Tests
as_data_frame = FALSE
)arrow
)feather
)Beobachtungen
Für diese bestimmte Datei
fread
ist eigentlich sehr schnell. Ich mag die kleine Dateigröße aus dem stark komprimiertenparquet2
Test. Ich kann die Zeit investieren, um mit dem nativen Datenformat zu arbeiten, anstatt mit einemdata.frame
wenn ich die Beschleunigung wirklich brauche.Hier
fst
ist auch eine gute Wahl. Ich würde entweder das stark komprimiertefst
Format oder das stark komprimierte Format verwenden,parquet
je nachdem, ob ich den Kompromiss zwischen Geschwindigkeit oder Dateigröße benötigte.quelle
Anstelle der herkömmlichen read.table ist fread meiner Meinung nach eine schnellere Funktion. Wenn Sie zusätzliche Attribute angeben, z. B. nur die erforderlichen Spalten auswählen, Spalten und Zeichenfolgen als Faktoren angeben, wird der Zeitaufwand für den Import der Datei verkürzt.
quelle
Ich habe alles oben versucht und [readr] [1] den besten Job gemacht. Ich habe nur 8 GB RAM
Schleife für 20 Dateien, jeweils 5 GB, 7 Spalten:
quelle