schnellste Möglichkeit, die ersten X Zeilen von einer Datei in eine andere innerhalb von R zu kopieren? (plattformübergreifend)

7

Ich kann die Datei nicht in den RAM laden (angenommen, ein Benutzer möchte vielleicht die erste Milliarde einer Datei mit zehn Milliarden Datensätzen)

hier ist meine Lösung, aber ich denke, dass es einen schnelleren Weg geben muss?

Danke

%Vor%     
Anthony Damico 17.11.2015, 10:58
quelle

8 Antworten

6

C ++ Lösung

Es ist nicht zu schwierig, C ++ - Code dafür zu schreiben:

%Vor%

Wenn Sie als yourfile.cpp gespeichert haben, können Sie

ausführen %Vor%

Von RStudio müssen Sie nichts laden. In der Konsole müssen Sie Rcpp laden. Sie müssen Rtools wahrscheinlich in Windows installieren.

Effizienterer R-Code

Indem Sie größere Blöcke statt einzelner Zeilen lesen, beschleunigt sich Ihr Code ebenfalls:

%Vor%

Benchmark

%Vor%

Ergebnisse in (Lösung0 ist die ursprüngliche Lösung des OP):

%Vor%

Die c ++ - Lösung kann wahrscheinlich beschleunigt werden, indem große Datenblöcke gleichzeitig eingelesen werden. Dies wird jedoch den Code viel komplexer machen. Wenn ich das nicht regelmäßig machen müsste, würde ich wahrscheinlich bei der reinen R-Lösung bleiben.

Anmerkung : Wenn Ihre Daten tabellarisch sind, können Sie mein LaF -Paket verwenden, um beliebige Zeilen und Spalten aus Ihrem Datensatz zu lesen, ohne dass alle Daten in den Speicher gelesen werden müssen.

    
Jan van der Laan 25.11.2015, 12:57
quelle
7

Sie können dafür ff::read.table.ffdf verwenden. Es speichert die Daten auf der Festplatte und es verwendet kein RAM.

%Vor%

Im Wesentlichen können Sie die obige Funktion wie base::read.table verwenden, mit dem Unterschied, dass das resultierende Objekt auf der Festplatte gespeichert wird.

Sie können auch das Argument nrow verwenden und eine bestimmte Anzahl von Zeilen laden. Die Dokumentation ist hier , wenn Sie etwas lesen möchten. Sobald Sie die Datei gelesen haben, können Sie die benötigten Zeilen unterteilen und sogar in data.frames konvertieren, wenn sie in den RAM passen.

Es gibt auch eine Funktion write.table.ffdf , mit der Sie ein ffdf -Objekt (resultierend aus read.table.ffdf ) schreiben können, was den Prozess noch einfacher macht.

Als Beispiel für die Verwendung von read.table.ffdf (oder read.delim.ffdf , was ziemlich genau das Gleiche ist) siehe Folgendes:

%Vor%

Ausgabe:

%Vor%

Wenn Sie eine txt-Datei verwenden, ist dies eine allgemeine Lösung, da jede Zeile mit einem \n -Zeichen endet.

    
LyzandeR 17.11.2015 13:33
quelle
6

Ich mag Rohre dafür, da wir andere Werkzeuge verwenden können. Und praktischerweise unterstützt die (wirklich ausgezeichnete) Verbindungsschnittstelle in R es:

%Vor%

Wenn wir das ausführen, erhalten wir die Zeilen vier bis sieben wie erwartet:

%Vor%

Beachten Sie, dass unsere Verwendung von sed keine Annahmen über die Dateistrukturen außer der Annahme von

gemacht hat
  • Standard "ascii" Textdatei, die im Textmodus gelesen werden soll
  • Standard-CR / LF-Zeilenendungen als 'Datensatzseparatoren'

Wenn Sie von Binärdateien mit unterschiedlichen Datensatztrennzeichen ausgehen, können wir verschiedene Lösungen vorschlagen.

Beachten Sie auch, dass Sie den Befehl steuern, der an die pipe() -Funktionen übergeben wird. Wenn Sie also die Zeilen 1000004 bis 1000007 verwenden möchten, ist die Verwendung genau gleich: Sie geben nur die erste und die letzte Zeile an (von jedem Segment kann es mehrere geben). Und anstelle von read.csv() könnte Ihr readLines() gleich gut verwendet werden.

Letztendlich ist sed überall verfügbar und, wenn der Speicher dient, auch Teil von Rtools. Die grundlegende Filterfunktionalität kann auch mit Perl oder einer Reihe anderer Tools erreicht werden.

    
Dirk Eddelbuettel 21.11.2015 16:07
quelle
3

Normalerweise beschleunige ich solche Schleifen, indem ich Teile von etwa 1000 Zeilen lese und schreibe. Wenn num_lines ein Vielfaches von 1000 ist, wird der Code:

%Vor%     
Andrey Shabalin 21.11.2015 23:55
quelle
3

Das Betriebssystem ist die beste Ebene für große Dateimanipulationen. Das ist schnell und kommt mit einem Benchmark (was wichtig erscheint, wenn das Poster nach einer schnelleren Methode gefragt wird):

%Vor%

Dies dauert ein paar Sekunden für Milliarden Zeilen. Ändere 29 zu 32, um etwa zehn Milliarden zu bekommen.

Dann in R, mit zehn Millionen Zeilen von der Milliarde (hundert Millionen viel zu langsam, um mit der Lösung des Posters zu vergleichen)

%Vor%

Und die Ergebnisse auf einem Mittelklasse-MacBook Pro, ein paar Jahre alt.

%Vor%

Würde mich interessieren, wie schnell die anderen Lösungen sind.

    
Jack Wasey 23.11.2015 21:24
quelle
2

Die "richtige" oder beste Antwort wäre eine Sprache, die mit Dateihandles viel einfacher funktioniert. Zum Beispiel, während perl in vielerlei Hinsicht eine hässliche Sprache ist, ist dies der Punkt, an dem es glänzt. Python kann dies auch auf eine ausführlichere Art und Weise tun.

Allerdings haben Sie explizit angegeben, dass Sie Dinge in R möchten. Zuerst nehme ich an, dass diese Sache möglicherweise nicht eine CSV- oder andere abgegrenzte flache Datei ist.

Verwenden Sie die Bibliothek readr . Verwenden Sie in dieser Bibliothek read_lines() . Etwas wie das (zuerst, erhalten Sie die Anzahl der Zeilen in der gesamten Datei, mit etwas wie das, was gezeigt wird hier ):

%Vor%

Ein paar Dinge zu beachten:

  1. Es gibt keine nette, praktische Möglichkeit, write in der Bibliothek readr zu schreiben, die so allgemein ist, wie es Ihnen scheint. (Es gibt zum Beispiel write_delim , aber Sie haben keine Begrenzung angegeben.)
  2. Alle Informationen, die in den vorherigen Inkarnationen von "outfile" enthalten sind, gehen verloren. Ich bin mir nicht sicher, ob Sie "outfile" im Append-Modus ( "a" ) öffnen wollten, aber ich vermute, das wäre hilfreich.
  3. Ich habe festgestellt, wenn ich mit großen Dateien wie dieser arbeite, möchte ich oft die Daten filtern, während ich sie so öffne. Die einfache Kopie zu tun scheint seltsam. Vielleicht möchtest du mehr tun?
  4. Wenn Sie eine Datei mit Trennzeichen haben, sollten Sie sich read_csv oder read_delim im Paket readr ansehen.
Mike Williamson 23.11.2015 21:15
quelle
2

Probieren Sie das Dienstprogramm head aus. Es sollte auf allen Betriebssystemen verfügbar sein, die R unterstützt (unter Windows wird davon ausgegangen, dass Rtools installiert ist und das Rtools bin-Verzeichnis sich auf Ihrem Pfad befindet). Um beispielsweise die ersten 100 Zeilen aus der Datei in.dat nach out.dat zu kopieren:

%Vor%     
G. Grothendieck 25.11.2015 23:03
quelle
-2

versuche es mit

%Vor%     
user_flow 17.11.2015 11:20
quelle

Tags und Links