Effizient mittlere die zweite Spalte nach Intervallen, die durch die erste Spalte definiert sind

7

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%     
jianfeng.mao 24.09.2011, 10:52
quelle

7 Antworten

7

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%     
42- 24.09.2011, 13:16
quelle
3
%Vor%     
FMc 24.09.2011 16:16
quelle
3

Angesichts der Größe Ihres Problems müssen Sie data.table verwenden, das blitzschnell ist.

%Vor%

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.

%Vor%

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.

    
Ramnath 24.09.2011 17:15
quelle
2

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

%Vor%

Übergeben Sie nun die gewünschte Funktion ( mean ) für jede Gruppe.

%Vor%

(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.

    
mdsumner 24.09.2011 12:03
quelle
2

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%     
Bill Ruppert 24.09.2011 13:38
quelle
2

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%     
hymloth 24.09.2011 11:19
quelle
2

Oneliner in Perl ist wie gewohnt einfach und effizient:

%Vor%     
Hynek -Pichi- Vychodil 24.09.2011 20:33
quelle

Tags und Links