Überblick
Ich bin relativ vertraut mit data.table, nicht so sehr mit dplyr. Ich habe einige dplyrVignetten und Beispiele gelesen , die auf SO aufgetaucht sind, und bisher sind meine Schlussfolgerungen folgende:
data.tableunddplyrsind in der Geschwindigkeit vergleichbar, außer wenn es viele (dh> 10-100K) Gruppen gibt, und unter einigen anderen Umständen (siehe Benchmarks unten)dplyrhat eine zugänglichere Syntaxdplyrabstrahiert (oder wird) mögliche DB-Interaktionen- Es gibt einige geringfügige Funktionsunterschiede (siehe "Beispiele / Verwendung" unten).
In meinen Augen hat 2. nicht viel Gewicht, weil ich ziemlich vertraut damit bin data.table, obwohl ich verstehe, dass es für Benutzer, die beide neu sind, ein großer Faktor sein wird. Ich möchte ein intuitiveres Argument vermeiden, da dies für meine spezifische Frage, die aus der Perspektive einer bereits vertrauten Person gestellt wird, irrelevant ist data.table. Ich möchte auch eine Diskussion darüber vermeiden, wie "intuitiver" zu einer schnelleren Analyse führt (sicherlich wahr, aber auch hier nicht das, woran ich hier am meisten interessiert bin).
Frage
Was ich wissen möchte ist:
- Gibt es analytische Aufgaben, die für Personen, die mit den Paketen vertraut sind, viel einfacher mit dem einen oder anderen Paket zu codieren sind (dh eine Kombination von erforderlichen Tastenanschlägen im Vergleich zum erforderlichen Grad an Esoterik, wobei weniger von jedem eine gute Sache ist).
- Gibt es analytische Aufgaben, die in einem Paket wesentlich effizienter (dh mehr als zweimal) effizienter ausgeführt werden als in einem anderen.
Eine aktuelle SO-Frage brachte mich dazu, ein bisschen mehr darüber nachzudenken, denn bis zu diesem Zeitpunkt dachte ich nicht, dass ich dplyrviel mehr bieten würde, als ich bereits tun kann data.table. Hier ist die dplyrLösung (Daten am Ende von Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Das war viel besser als mein Hackversuch nach einer data.tableLösung. Trotzdem sind gute data.tableLösungen auch ziemlich gut (danke Jean-Robert, Arun, und beachten Sie, dass ich hier eine einzelne Aussage der streng optimalen Lösung vorgezogen habe):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
Die Syntax für Letzteres mag sehr esoterisch erscheinen, aber es ist tatsächlich ziemlich einfach, wenn Sie es gewohnt sind data.table(dh einige der esoterischeren Tricks werden nicht verwendet).
Im Idealfall , was ich möchte sehen , ist einige gute Beispiele waren die dplyroder data.tableArt und Weise wesentlich prägnanter oder führt wesentlich besser.
Beispiele
Verwendungszweckdplyrerlaubt keine gruppierten Operationen, die eine beliebige Anzahl von Zeilen zurückgeben (aus der Frage von eddi , Anmerkung: Dies sieht so aus, als würde es in dplyr 0.5 implementiert , außerdem zeigt @beginneR eine mögliche Problemumgehungdoin der Antwort auf die Frage von @ eddi).data.tableunterstützt rollierende Joins (danke @dholstius) sowie überlappende Joinsdata.tableintern optimiert Ausdrücke der FormDT[col == value]oderDT[col %in% values]für die Geschwindigkeit durch die automatische Indexierung , die verwendet binäre Suche , während der gleichen Grund R Syntax. Hier finden Sie weitere Details und einen kleinen Benchmark.dplyrbietet Standard - Testversionen von Funktionen (zBregroup,summarize_each_) dass die programmatische Verwendung vereinfachen kanndplyr(Hinweis programmatische Verwendung vondata.tablezumindest meines Wissens ist auf jeden Fall möglich, einige sorgfältige Überlegungen erfordert nur, Substitution / zitieren, etc,)
- Ich habe meine eigenen Benchmarks durchgeführt und festgestellt, dass beide Pakete in der Analyse des "Split Apply Combine" -Stils vergleichbar sind, es sei denn, es gibt eine sehr große Anzahl von Gruppen (> 100 KB), bei denen der Punkt
data.tablewesentlich schneller wird. - @Arun führte einige Benchmarks für Joins durch und zeigte, dass die
data.tableSkalierung besser ist alsdplyrmit zunehmender Anzahl von Gruppen (aktualisiert mit den jüngsten Verbesserungen in beiden Paketen und der neuesten Version von R). Auch wenn eine Benchmark zu bekommen versuchen , eindeutige Werte hatdata.table~ 6x schneller. - (Nicht überprüft) ist
data.tablebei größeren Versionen einer Gruppe / Anwenden / Sortieren um 75% schneller, beidplyrkleineren um 40% schneller (eine weitere SO-Frage aus Kommentaren , danke danas). - Matt, der Hauptautor
data.table, hat gebenchmarkt Operationen auf Gruppierungdata.table,dplyrund Pythonpandasauf bis zu 2 Milliarden Zeilen (~ 100 GB RAM) . - Ein älterer Benchmark für 80K-Gruppen ist
data.table~ 8x schneller
Daten
Dies ist das erste Beispiel, das ich im Fragenbereich gezeigt habe.
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
dplyrund data.tableTeams an Benchmarks, daher wird irgendwann eine Antwort da sein. # 2 (Syntax) imO ist streng falsch, aber das wagt sich eindeutig in das Meinungsgebiet, also stimme ich auch dafür, zu schließen.
(d)plyrhat Maßnahme 0
dplyrund plyrin Bezug auf die Syntax wirklich nervt und im Grunde der Hauptgrund ist, warum ich ihre Syntax nicht mag, ist, dass ich viel zu viele (mehr als 1) zusätzliche Funktionen lernen muss (mit Namen, die immer noch sind macht für mich keinen Sinn), erinnere dich daran, was sie tun, welche Argumente sie nehmen usw. Das war für mich immer eine große Abkehr von der Plyr-Philosophie.
.SD. B. ). [ernsthaft] Ich denke, dies sind legitime Designunterschiede, die unterschiedliche Menschen ansprechen werden
dplyrist, ist:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]