In einer Datendatei gibt es zwei numerische Spalten. Ich muss den Durchschnitt der zweiten Spalte nach Intervallen (z. B. 100) der ersten Spalte berechnen.
Ich kann diese Aufgabe in R programmieren, aber mein R-Code ist wirklich langsam für eine relativ große Datendatei (Millionen von Zeilen, wobei sich der Wert der ersten Spalte zwischen 1 und 33132539 ändert).
Hier zeige ich meinen R-Code. Wie könnte ich es tun, um schneller zu sein? Andere Lösungen, die perl-, python-, awk- oder shell-basiert sind, werden geschätzt.
Vielen Dank im Voraus.
(1) meine Datendatei (durch Tabulatorzeichen getrennt, Millionen von Zeilen)
%Vor%(2) was ich bekommen möchte, hier Intervall = 100
%Vor%(3) R-Code
%Vor%Sie müssen nicht wirklich einen Ausgabedatenrahmen einrichten, aber Sie können, wenn Sie wollen. Hier ist, wie ich es codiert hätte, und ich garantiere, dass es schnell sein wird.
%Vor%Sie hätten noch weniger Einstellungen vornehmen können (überspringen Sie die Variable incrmt mit diesem Code:
%Vor%Und wenn das Ergebnis für etwas verfügbar sein soll:
%Vor% Angesichts der Größe Ihres Problems müssen Sie data.table
verwenden, das blitzschnell ist.
Dies dauerte 20 Sekunden auf meinem Macbook Pro mit Spezifikationen 2.53Ghz 4GB RAM. Wenn Sie NA
in Ihrer zweiten Spalte nicht haben, können Sie eine 10fache Beschleunigung erzielen, indem Sie mean
durch .Internal(mean)
ersetzen.
Hier ist der Geschwindigkeitsvergleich mit rbenchmark
und 5 Replikationen. Beachten Sie, dass data.table
mit .Internal(mean)
10x schneller ist.
Aktualisierung von Matthew:
Neu in v1.8.2, diese Optimierung (ersetzt mean
mit .Internal(mean)
) wird nun automatisch gemacht; h., reguläre DT[,mean(somecol),by=]
läuft jetzt mit der 10-fachen Geschwindigkeit. Wir werden versuchen, in Zukunft mehr Convenience-Änderungen vorzunehmen, damit die Benutzer nicht so viele Tricks kennen müssen, um das Beste aus data.table
zu erhalten.
Basierend auf Ihrem Code würde ich vermuten, dass dies den gesamten Datensatz (je nach Speicher Ihres Systems) funktionieren würde:
%Vor% Ich denke, Sie möchten einen Faktor, der Gruppen von Intervallen für alle 100 innerhalb der ersten Spalte ( rho
) definiert, und dann können Sie die Standardfunktionsfamilie anwenden, um Mittelwerte innerhalb von Gruppen zu erhalten.
Hier sind die Daten, die Sie in reproduzierbarer Form veröffentlicht haben.
%Vor% Definieren Sie die Intervalle mit cut
, wir wollen nur jeden 100sten Wert (aber Sie möchten vielleicht die Details nach Ihrem Code für Ihren realen Datensatz optimiert).
Übergeben Sie nun die gewünschte Funktion ( mean
) für jede Gruppe.
(Viele NAs, da wir nicht bei 0 gestartet haben, dann)
%Vor%(Fügen Sie FUN weitere Argumente hinzu, z. B. na.rm, falls erforderlich.)
%Vor% Siehe ?tapply
über Gruppen in einem Vektor (zackiges Array) und ?cut
, um Gruppierungsfaktoren zu generieren.
Hier ist ein Perl-Programm, das genau das tut, was Sie wollen. Es wird davon ausgegangen, dass die Zeilen nach der ersten Spalte sortiert sind.
%Vor%Das erste, was uns in den Sinn kommt, ist ein Python-Generator, der speichereffizient ist.
%Vor%Dann fügen Sie eine Logik in eine andere Funktion ein (und nehmen an, dass Sie die Ergebnisse in einer Datei speichern)
%Vor%BEARBEITEN : Die obige Lösung ging davon aus, dass die Zahlen in der ersten Spalte ALLE Zahlen von 1 bis N sind. Da Ihr Fall diesem Muster (aus den zusätzlichen Details in den Kommentaren) nicht folgt, hier ist die richtige Funktion:
%Vor%Oneliner in Perl ist wie gewohnt einfach und effizient:
%Vor%Tags und Links python r perl data.table awk