Zum Beispiel (nicht sicher, ob das repräsentativste Beispiel):
N <- 1e6
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
Das habe ich bisher:
d <- merge(d1,d2)
# 7.6 sec
library(plyr)
d <- join(d1,d2)
# 2.9 sec
library(data.table)
dt1 <- data.table(d1, key="x")
dt2 <- data.table(d2, key="x")
d <- data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
# 4.9 sec
library(sqldf)
sqldf()
sqldf("create index ix1 on d1(x)")
sqldf("create index ix2 on d2(x)")
d <- sqldf("select * from d1 inner join d2 on d1.x=d2.x")
sqldf()
# 17.4 sec
performance
r
join
merge
data.table
datasmurf
quelle
quelle
Antworten:
Der Übereinstimmungsansatz funktioniert, wenn im zweiten Datenrahmen für jeden Schlüsselwert im ersten ein eindeutiger Schlüssel vorhanden ist. Wenn der zweite Datenrahmen Duplikate enthält, sind die Übereinstimmungs- und Zusammenführungsansätze nicht identisch. Das Match ist natürlich schneller, da es nicht so viel bewirkt. Insbesondere wird nie nach doppelten Schlüsseln gesucht. (Fortsetzung nach Code)
In dem in der Frage veröffentlichten sqldf-Code scheint es, dass Indizes für die beiden Tabellen verwendet wurden, aber tatsächlich werden sie in Tabellen platziert, die überschrieben wurden, bevor die sql-Auswahl jemals ausgeführt wird, und dies erklärt teilweise, warum Es ist so langsam. Die Idee von sqldf ist, dass die Datenrahmen in Ihrer R-Sitzung die Datenbank bilden, nicht die Tabellen in sqlite. Daher sucht der Code jedes Mal, wenn er auf einen nicht qualifizierten Tabellennamen verweist, in Ihrem R-Arbeitsbereich danach - nicht in der Hauptdatenbank von sqlite. Daher wird in der angezeigten select-Anweisung d1 und d2 aus dem Arbeitsbereich in die Hauptdatenbank von sqlite eingelesen, wobei diejenigen mit den Indizes überlastet werden. Infolgedessen wird ein Join ohne Indizes ausgeführt. Wenn Sie die Versionen von d1 und d2 verwenden möchten, die sich in der Hauptdatenbank von sqlite befinden, müssen Sie sie als main.d1 und main bezeichnen. d2 und nicht als d1 und d2. Wenn Sie versuchen, die Ausführung so schnell wie möglich zu gestalten, beachten Sie, dass bei einem einfachen Join keine Indizes für beide Tabellen verwendet werden können, sodass Sie Zeit beim Erstellen eines der Indizes sparen können. Im folgenden Code veranschaulichen wir diese Punkte.
Es lohnt sich zu bemerken, dass die genaue Berechnung einen großen Unterschied machen kann, welches Paket am schnellsten ist. Zum Beispiel führen wir unten eine Zusammenführung und ein Aggregat durch. Wir sehen, dass die Ergebnisse für beide nahezu umgekehrt sind. Im ersten Beispiel vom schnellsten zum langsamsten erhalten wir: data.table, plyr, merge und sqldf, während im zweiten Beispiel sqldf, aggregat, data.table und plyr - fast das Gegenteil des ersten. Im ersten Beispiel ist sqldf 3x langsamer als data.table und im zweiten 200x schneller als plyr und 100-mal schneller als data.table. Unten zeigen wir den Eingabecode, die Ausgabezeiten für die Zusammenführung und die Ausgabezeiten für das Aggregat. Es ist auch erwähnenswert, dass sqldf auf einer Datenbank basiert und daher Objekte verarbeiten kann, die größer als R sind (wenn Sie das Argument dbname von sqldf verwenden), während die anderen Ansätze auf die Verarbeitung im Hauptspeicher beschränkt sind. Wir haben auch sqldf mit sqlite illustriert, aber es unterstützt auch die H2- und PostgreSQL-Datenbanken.
Die Ergebnisse der beiden Benchmark-Aufrufe, die die Zusammenführungsberechnungen vergleichen, sind:
Die Ausgabe des Benchmark-Aufrufs zum Vergleich der aggregierten Berechnungen lautet:
quelle
Die 132 Sekunden, die in Gabors Ergebnissen für angegeben sind,
data.table
sind tatsächlich Timing-BasisfunktionencolMeans
undcbind
(die Speicherzuweisung und das Kopieren, die durch die Verwendung dieser Funktionen induziert werden). Es gibt auch gute und schlechte Verwendungsmöglichkeitendata.table
.Bitte beachten Sie, dass ich Plyr nicht gut kenne. Bitte erkundigen Sie sich bei Hadley, bevor Sie sich auf die
plyr
Zeitangaben hier verlassen. Beachten Sie auch, dass indata.table
do die Zeit zum Konvertierendata.table
und Festlegen des Schlüssels für die Fareness enthalten ist.Diese Antwort wurde aktualisiert, seit sie ursprünglich im Dezember 2010 beantwortet wurde. Die vorherigen Benchmark-Ergebnisse sind unten aufgeführt. Bitte sehen Sie im Versionsverlauf dieser Antwort nach, was sich geändert hat.
quelle
.Internal
Aufrufe in CRAN-Paketen verwenden (siehe CRAN-Repository-Richtlinie) .data.table
automatisch optimiert wirdmean
(ohne.Internal
intern anzurufen ).for
Schleife gut, das ist gut. Könnten Sie diesem Problem weitere Informationen zur "SEM-Analyse" hinzufügen? Zum Beispiel vermute ich, dass SEM = Rasterelektronenmikroskop? Wenn wir mehr über die Anwendung wissen, wird sie für uns interessanter und hilft uns, Prioritäten zu setzen.Für einfache Aufgaben (eindeutige Werte auf beiden Seiten der Verknüpfung) verwende ich
match
:Es ist weitaus schneller als das Zusammenführen (auf meinem Computer 0,13 bis 3,37 Sekunden).
Meine Timings:
merge
: 3,32splyr
: 0,84 smatch
: 0,12 squelle
Ich dachte, es wäre interessant, einen Benchmark mit dplyr in der Mischung zu veröffentlichen: (viele Dinge liefen)
Gerade hinzugefügt:
und richten Sie die Daten für dplyr mit einer Datentabelle ein:
Aktualisiert: Ich habe data.tableBad und plyr entfernt und nichts als RStudio geöffnet (i7, 16 GB RAM).
Mit data.table 1.9 und dplyr mit Datenrahmen:
Mit data.table 1.9 und dplyr mit Datentabelle:
Aus Gründen der Konsistenz ist hier das Original mit all und data.table 1.9 und dplyr unter Verwendung einer Datentabelle:
Ich denke, diese Daten sind zu klein für die neuen data.table und dplyr :)
Größerer Datensatz:
Es dauerte ungefähr 10-13 GB RAM, um die Daten zu speichern, bevor der Benchmark ausgeführt wurde.
Ergebnisse:
Versuchte eine Milliarde, sprengte aber Widder. 32 GB werden es problemlos bewältigen.
[Edit by Arun] (dotcomken, könnten Sie bitte diesen Code ausführen und Ihre Benchmarking-Ergebnisse einfügen? Danke).
Gemäß Aruns Anfrage hier die Ausgabe dessen, was Sie mir zur Verfügung gestellt haben:
Entschuldigung für die Verwirrung, spät in der Nacht kam zu mir.
Die Verwendung von dplyr mit Datenrahmen scheint die weniger effiziente Methode zur Verarbeitung von Zusammenfassungen zu sein. Ist diese Methode, um die genaue Funktionalität von data.table und dplyr mit den enthaltenen Datenstrukturmethoden zu vergleichen? Ich würde es fast vorziehen, das zu trennen, da die meisten Daten bereinigt werden müssen, bevor wir group_by oder die data.table erstellen. Es könnte Geschmackssache sein, aber ich denke, der wichtigste Teil ist, wie effizient die Daten modelliert werden können.
quelle
Mithilfe der Zusammenführungsfunktion und ihrer optionalen Parameter:
Innerer Join: Merge (df1, df2) funktioniert für diese Beispiele, da R die Frames automatisch über allgemeine Variablennamen verbindet. Sie möchten jedoch höchstwahrscheinlich Merge (df1, df2, by = "CustomerId") angeben, um sicherzustellen, dass Sie dies tun wurden nur auf den von Ihnen gewünschten Feldern abgeglichen. Sie können auch die Parameter by.x und by.y verwenden, wenn die übereinstimmenden Variablen in den verschiedenen Datenrahmen unterschiedliche Namen haben.
quelle