Überblick
Ich bin relativ vertraut mit data.table
, nicht so sehr mit dplyr
. Ich habe einige dplyr
Vignetten und Beispiele gelesen , die auf SO aufgetaucht sind, und bisher sind meine Schlussfolgerungen folgende:
data.table
unddplyr
sind in der Geschwindigkeit vergleichbar, außer wenn es viele (dh> 10-100K) Gruppen gibt, und unter einigen anderen Umständen (siehe Benchmarks unten)dplyr
hat eine zugänglichere Syntaxdplyr
abstrahiert (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 dplyr
viel mehr bieten würde, als ich bereits tun kann data.table
. Hier ist die dplyr
Lö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.table
Lösung. Trotzdem sind gute data.table
Lö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 dplyr
oder data.table
Art und Weise wesentlich prägnanter oder führt wesentlich besser.
Beispiele
Verwendungszweckdplyr
erlaubt 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 Problemumgehungdo
in der Antwort auf die Frage von @ eddi).data.table
unterstützt rollierende Joins (danke @dholstius) sowie überlappende Joinsdata.table
intern 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.dplyr
bietet Standard - Testversionen von Funktionen (zBregroup
,summarize_each_
) dass die programmatische Verwendung vereinfachen kanndplyr
(Hinweis programmatische Verwendung vondata.table
zumindest 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.table
wesentlich schneller wird. - @Arun führte einige Benchmarks für Joins durch und zeigte, dass die
data.table
Skalierung besser ist alsdplyr
mit 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.table
bei größeren Versionen einer Gruppe / Anwenden / Sortieren um 75% schneller, beidplyr
kleineren um 40% schneller (eine weitere SO-Frage aus Kommentaren , danke danas). - Matt, der Hauptautor
data.table
, hat gebenchmarkt Operationen auf Gruppierungdata.table
,dplyr
und Pythonpandas
auf 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))
dplyr
und data.table
Teams 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)plyr
hat Maßnahme 0
dplyr
und plyr
in 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
dplyr
ist, ist:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]