Ü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))
quelle
dplyr
ist, ist:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]
dplyr
unddata.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 0dplyr
undplyr
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 werdenAntworten:
Wir müssen Abdeckung zumindest diese Aspekte eine umfassende Antwort / Vergleich zur Verfügung zu stellen (in keiner bestimmten Reihenfolge ihrer Bedeutung):
Speed
,Memory usage
,Syntax
undFeatures
.Meine Absicht ist es, jedes dieser Themen aus Sicht der Datentabelle so klar wie möglich zu behandeln.
Die data.table-Syntax ist in ihrer Form konsistent -
DT[i, j, by]
. Zu halteni
,j
undby
gemeinsam ist konstruktionsbedingt . Durch das Zusammenhalten verwandter Vorgänge können Vorgänge auf einfache Weise hinsichtlich Geschwindigkeit und vor allem der Speichernutzung optimiert und einige leistungsstarke Funktionen bereitgestellt werden , während die Konsistenz der Syntax erhalten bleibt.1. Geschwindigkeit
Nicht wenige Benchmarks (obwohl hauptsächlich zu Gruppierungsvorgängen) wurden zu der Frage hinzugefügt, die bereits Daten anzeigt. Die Tabelle wird schneller als dplyr, da die Anzahl der zu gruppierenden Gruppen und / oder Zeilen zunimmt, einschließlich der Benchmarks von Matt für die Gruppierung von 10 Millionen auf 2 Milliarden Zeilen ( 100 GB im RAM) in 100 - 10 Millionen Gruppen und unterschiedlichen Gruppierungsspalten, was ebenfalls vergleichbar ist
pandas
. Siehe auch aktualisierte Benchmarks , einschließlichSpark
undpydatatable
.Bei Benchmarks wäre es großartig, auch diese verbleibenden Aspekte abzudecken:
Gruppierungsoperationen, die eine Teilmenge von Zeilen umfassen, dh
DT[x > val, sum(y), by = z]
Operationen vom Typ.Benchmark andere Operationen wie Update und schließt sich .
Zusätzlich zur Laufzeit wird auch der Speicherbedarf für jeden Vorgang gemessen.
2. Speichernutzung
Operationen mit
filter()
oderslice()
in dplyr können speichereffizient sein (sowohl auf data.frames als auch auf data.tables). Siehe diesen Beitrag .Die Schnittstelle data.table ermöglicht es derzeit, Spalten anhand von Referenzen zu ändern / zu aktualisieren (beachten Sie, dass wir das Ergebnis nicht erneut einer Variablen zuweisen müssen).
Dplyr wird jedoch niemals durch Referenz aktualisiert. Das dplyr-Äquivalent wäre (beachten Sie, dass das Ergebnis neu zugewiesen werden muss):
Ein Anliegen hierfür ist die referenzielle Transparenz . Das Aktualisieren eines data.table-Objekts durch Referenz, insbesondere innerhalb einer Funktion, ist möglicherweise nicht immer wünschenswert. Dies ist jedoch eine unglaublich nützliche Funktion: In diesem und diesen Beiträgen finden Sie interessante Fälle. Und wir wollen es behalten.
Daher arbeiten wir daran,
shallow()
Funktionen in data.table zu exportieren , die dem Benutzer beide Möglichkeiten bieten . Wenn es beispielsweise wünschenswert ist, die Eingabedatentabelle innerhalb einer Funktion nicht zu ändern, kann man Folgendes tun:Wenn Sie nicht verwenden
shallow()
, bleibt die alte Funktionalität erhalten:Wenn Sie eine flache Kopie mit erstellen
shallow()
, verstehen Sie, dass Sie das Originalobjekt nicht ändern möchten. Wir kümmern uns intern um alles, um sicherzustellen, dass Sie Spalten, die Sie ändern, nur dann kopieren, wenn dies unbedingt erforderlich ist . Bei der Implementierung sollte dies das Problem der referenziellen Transparenz vollständig lösen und dem Benutzer beide Möglichkeiten bieten.Beim Beitritt aggregieren:
Angenommen, Sie haben zwei data.tables wie folgt:
Und Sie möchten
sum(z) * mul
für jede ZeileDT2
beim Verbinden durch Spalten erhaltenx,y
. Wir können entweder:1) aggregieren
DT1
, um zu erhaltensum(z)
, 2) einen Join durchführen und 3) multiplizieren (oder)2) Machen Sie alles auf einmal (mit der
by = .EACHI
Funktion):Was ist der Vorteil?
Wir müssen keinen Speicher für das Zwischenergebnis zuweisen.
Wir müssen nicht zweimal gruppieren / hashen (eine für die Aggregation und eine für das Beitreten).
Und was noch wichtiger ist, die Operation, die wir durchführen wollten, wird anhand von
j
(2) deutlich.Überprüfen Sie diesen Beitrag für eine detaillierte Erklärung von
by = .EACHI
. Es werden keine Zwischenergebnisse erzielt, und das Join + Aggregat wird auf einmal ausgeführt.Schauen Sie sich diesen , diesen und diesen Beitrag für reale Nutzungsszenarien an.
In
dplyr
müsste man zuerst beitreten und aggregieren oder aggregieren und dann beitreten , von denen keines in Bezug auf den Speicher so effizient ist (was sich wiederum in Geschwindigkeit niederschlägt).Aktualisieren und beitreten:
Betrachten Sie den unten gezeigten data.table-Code:
fügt / updates
DT1
‚s Spaltecol
mitmul
ausDT2
auf diesen Zeilen , in denenDT2
‘ s Schlüsselspalte StreichhölzerDT1
. Ich glaube nicht, dass es ein genaues Äquivalent zu dieser Operation gibtdplyr
, dh ohne eine*_join
Operation zu vermeiden , die das Ganze kopieren müsste,DT1
nur um eine neue Spalte hinzuzufügen, was unnötig ist.Überprüfen Sie diesen Beitrag auf ein reales Nutzungsszenario.
3. Syntax
Schauen wir uns nun die Syntax an . Hadley kommentierte hier :
Ich finde diese Bemerkung sinnlos, weil sie sehr subjektiv ist. Was wir vielleicht versuchen können, ist, die Konsistenz in der Syntax gegenüberzustellen . Wir werden data.table und dplyr-Syntax nebeneinander vergleichen.
Wir werden mit den unten gezeigten Dummy-Daten arbeiten:
Grundlegende Aggregations- / Aktualisierungsvorgänge.
Die Syntax von data.table ist kompakt und dplyr ist ziemlich ausführlich. In Fall (a) sind die Dinge mehr oder weniger gleichwertig.
In Fall (b) mussten wir
filter()
beim Zusammenfassen in dplyr verwenden . Aber während der Aktualisierung mussten wir die Logik nach innen verschiebenmutate()
. In data.table drücken wir jedoch beide Operationen mit derselben Logik aus - arbeiten Sie mit Zeilenx > 2
, in denen , aber im ersten Fall, getsum(y)
, während im zweiten Fall diese Zeileny
mit ihrer kumulativen Summe aktualisiert werden .Das meinen wir, wenn wir sagen, dass die
DT[i, j, by]
Form konsistent ist .In ähnlicher Weise können wir in Fall (c), wenn wir eine
if-else
Bedingung haben, die Logik "wie sie ist" sowohl in data.table als auch in dplyr ausdrücken. Wenn wir jedoch nur die Zeilen zurückgeben möchten, in denen dieif
Bedingung erfüllt ist, und ansonsten überspringensummarise()
möchten , können wir nicht direkt verwenden (AFAICT). Wir müssenfilter()
zuerst und dann zusammenfassen, weilsummarise()
immer ein einziger Wert erwartet wird .Während es das gleiche Ergebnis zurückgibt,
filter()
macht die Verwendung hier die tatsächliche Operation weniger offensichtlich.Es könnte sehr gut möglich sein, es auch
filter()
im ersten Fall zu verwenden (scheint mir nicht offensichtlich zu sein), aber mein Punkt ist, dass wir es nicht müssen sollten.Aggregation / Aktualisierung für mehrere Spalten
In Fall (a) sind die Codes mehr oder weniger äquivalent. data.table verwendet die bekannte Basisfunktion
lapply()
, währenddplyr
es*_each()
zusammen mit einer Reihe von Funktionen eingeführt wirdfuns()
.Für data.table
:=
müssen Spaltennamen angegeben werden, während dplyr diese automatisch generiert.In Fall (b) ist die Syntax von dplyr relativ einfach. Das Verbessern von Aggregationen / Aktualisierungen für mehrere Funktionen steht in der Liste von data.table.
In Fall (c) würde dplyr jedoch nicht
n()
nur einmal, sondern so oft wie viele Spalten zurückgeben. In data.table müssen wir lediglich eine Liste in zurückgebenj
. Jedes Element der Liste wird zu einer Spalte im Ergebnis. Wir können also wieder die bekannte Basisfunktion verwendenc()
,.N
um eine zu verketten ,list
die a zurückgibtlist
.Tritt bei
dplyr bietet separate Funktionen für jeden Join-Typ, wobei data.table Joins mit derselben Syntax
DT[i, j, by]
(und mit gutem Grund) zulässt .merge.data.table()
Alternativ bietet es auch eine äquivalente Funktion.Einige finden möglicherweise eine separate Funktion für jede Verknüpfung viel besser (links, rechts, inner, anti, semi usw.), während andere möglicherweise data.table's mögen
DT[i, j, by]
odermerge()
die Basis R ähneln.Dplyr-Joins tun genau das. Nichts mehr. Nicht weniger.
data.tables kann Spalten beim Verbinden auswählen (2), und in dplyr müssen Sie
select()
zuerst beide data.frames bearbeiten, bevor Sie wie oben gezeigt verbinden können. Andernfalls würden Sie den Join mit unnötigen Spalten materialisieren, um sie später zu entfernen, und das ist ineffizient.data.tables können mithilfe der Funktion beim Beitritt (3) aggregiert und beim Beitritt (4) aktualisiert werden
by = .EACHI
. Warum das gesamte Join-Ergebnis materialisieren, um nur wenige Spalten hinzuzufügen / zu aktualisieren?data.table der Lage ist , Rollen verbindet (5) - Rolle vorwärts, LOCF , Rolle rückwärts, NOCB , am nächsten .
data.table hat auch ein
mult =
Argument, das die erste , letzte oder alle Übereinstimmungen auswählt (6).data.table hat ein
allow.cartesian = TRUE
Argument zum Schutz vor versehentlichen ungültigen Verknüpfungen .do()
...Die Zusammenfassung von dplyr wurde speziell für Funktionen entwickelt, die einen einzelnen Wert zurückgeben. Wenn Ihre Funktion mehrere / ungleiche Werte zurückgibt, müssen Sie darauf zurückgreifen
do()
. Sie müssen im Voraus über alle Ihre Funktionen Rückgabewert wissen..SD
Das Äquivalent ist.
In data.table können Sie so ziemlich alles einwerfen. Sie müssen sich
j
nur daran erinnern, dass eine Liste zurückgegeben wird, damit jedes Element der Liste in eine Spalte konvertiert wird.In dplyr kann das nicht.
do()
Je nachdem, wie sicher Sie sind, ob Ihre Funktion immer einen einzelnen Wert zurückgeben würde, müssen Sie darauf zurückgreifen . Und es ist ziemlich langsam.Schauen Sie sich diese und diese SO-Frage an . Ich frage mich, ob es möglich wäre, die Antwort mit der Syntax von dplyr als einfach auszudrücken ...
4. Funktionen
Ich habe auf die meisten Funktionen hier und auch in diesem Beitrag hingewiesen . In Ergänzung:
fread - schneller Dateireader ist seit langem verfügbar.
fwrite - ein parallelisierter schneller Dateischreiber ist jetzt verfügbar. In diesem Beitrag finden Sie eine detaillierte Erläuterung zur Implementierung und in # 1664 weitere Entwicklungen.
Automatische Indizierung - eine weitere praktische Funktion zur internen Optimierung der Basis-R-Syntax.
Ad-hoc-Gruppierung :
dplyr
Sortiert die Ergebnisse automatisch nach Gruppierung von Variablen währendsummarise()
, was möglicherweise nicht immer wünschenswert ist.Zahlreiche Vorteile der oben genannten data.table-Joins (für Geschwindigkeits- / Speichereffizienz und Syntax).
Non-Equi-Joins : Ermöglicht Joins mit anderen Operatoren
<=, <, >, >=
sowie alle anderen Vorteile von data.table-Joins.Überlappende Bereichsverknüpfungen wurden kürzlich in data.table implementiert. Überprüfen Sie diesen Beitrag für eine Übersicht mit Benchmarks.
setorder()
Funktion in data.table, die eine sehr schnelle Neuordnung von data.tables anhand von Referenzen ermöglicht.dplyr bietet eine Schnittstelle zu Datenbanken mit derselben Syntax, die data.table derzeit nicht verwendet.
data.table
bietet Äquivalente schnelle Mengenoperationen (von Jan Gorecki geschrieben) -fsetdiff
,fintersect
,funion
undfsetequal
mit zusätzlichemall
Argumente (wie in SQL).data.table wird sauber und ohne Maskierungswarnungen geladen und verfügt über einen hier beschriebenen Mechanismus zur
[.data.frame
Kompatibilität, wenn er an ein R-Paket übergeben wird. dplyr ändert Basisfunktionenfilter
,lag
und[
was zu Problemen führen kann; zB hier und hier .Schließlich:
In Datenbanken - es gibt keinen Grund, warum data.table keine ähnliche Schnittstelle bereitstellen kann, aber dies hat derzeit keine Priorität. Es könnte zu Problemen kommen, wenn Benutzer diese Funktion sehr mögen würden. Ich bin mir nicht sicher.
Über Parallelität - Alles ist schwierig, bis jemand weitermacht und es tut. Natürlich wird es Mühe kosten (threadsicher zu sein).
OpenMP
.quelle
:=
) verwenden,dplyr
Äquivalent auch<-
wie inDF <- DF %>% mutate...
anstelle von nur verwenden sollteDF %>% mutate...
dplyr
dass dies für Benutzer, die früherplyr
Syntaxdata.table
verwendet haben, einfacher sein kann , aber für Benutzer, die früher die Syntax von Sprachen abfragtenSQL
, und für die dahinter stehende relationale Algebra, bei der es um die tabellarische Datentransformation geht, einfacher sein kann . @Arun Sie sollten beachten, dass Set-Operatoren sehr einfach durch die Wrapping-data.table
Funktion ausgeführt werden können und natürlich eine erhebliche Beschleunigung bringen.Hier ist mein Versuch, eine umfassende Antwort aus der Perspektive von dplyr zu finden, die dem breiten Umriss von Aruns Antwort folgt (aber aufgrund unterschiedlicher Prioritäten etwas neu geordnet).
Syntax
Die Syntax ist etwas subjektiv, aber ich stehe zu meiner Aussage, dass die Prägnanz von data.table das Lernen und Lesen erschwert. Dies liegt zum Teil daran, dass dplyr ein viel einfacheres Problem löst!
Eine wirklich wichtige Sache, die dplyr für Sie tut, ist, dass es Ihre Optionen einschränkt . Ich behaupte, dass die meisten Einzeltabellenprobleme mit nur fünf Schlüsselverben gelöst werden können, die gefiltert, ausgewählt, mutiert, angeordnet und zusammengefasst werden, zusammen mit einem Adverb "nach Gruppe". Diese Einschränkung ist eine große Hilfe, wenn Sie Datenmanipulation lernen, da sie Ihnen hilft, über das Problem nachzudenken. In dplyr wird jedes dieser Verben einer einzelnen Funktion zugeordnet. Jede Funktion erledigt einen Job und ist isoliert leicht zu verstehen.
Sie schaffen Komplexität, indem Sie diese einfachen Operationen zusammen mit
%>%
. Hier ist ein Beispiel aus einem der Beiträge, mit denen Arun verlinkt ist :Selbst wenn Sie dplyr noch nie zuvor gesehen haben (oder sogar R!), Können Sie sich dennoch ein Bild davon machen, was passiert, da die Funktionen alle englische Verben sind. Der Nachteil von englischen Verben ist, dass sie mehr Eingabe erfordern als
[
, aber ich denke, dass dies durch eine bessere automatische Vervollständigung weitgehend gemildert werden kann.Hier ist der entsprechende data.table-Code:
Es ist schwieriger, diesem Code zu folgen, wenn Sie nicht bereits mit data.table vertraut sind. (Ich konnte auch nicht herausfinden, wie ich das Wiederholte
[
auf eine Weise einrücken kann, die für mein Auge gut aussieht). Wenn ich mir Code anschaue, den ich vor 6 Monaten geschrieben habe, ist das wie ein Code, der von einem Fremden geschrieben wurde. Daher bevorzuge ich einfachen, wenn auch ausführlichen Code.Zwei weitere kleine Faktoren, die meiner Meinung nach die Lesbarkeit leicht beeinträchtigen:
Da fast jede Datentabellenoperation verwendet wird
[
, benötigen Sie zusätzlichen Kontext, um herauszufinden, was passiert.x[y]
Verbinden Sie beispielsweise zwei Datentabellen oder extrahieren Sie Spalten aus einem Datenrahmen? Dies ist nur ein kleines Problem, da in gut geschriebenem Code die Variablennamen darauf hinweisen sollten, was passiert.Ich mag das
group_by()
ist eine separate Operation in dplyr. Es ändert die Berechnung grundlegend, so dass ich denke, dass es beim Überfliegen des Codes offensichtlich sein sollte, und es ist einfacher zu erkennengroup_by()
als dasby
Argument dafür[.data.table
.Mir gefällt auch, dass die Pipe nicht nur auf ein Paket beschränkt ist. Sie können beginnen, indem Sie Ihre Daten mit tidyr aufräumen und mit einem Plot in ggvis abschließen . Und Sie sind nicht auf die Pakete beschränkt, die ich schreibe - jeder kann eine Funktion schreiben, die einen nahtlosen Teil einer Datenmanipulations-Pipe bildet. Tatsächlich bevorzuge ich lieber den vorherigen data.table-Code, der umgeschrieben wurde mit
%>%
:Und die Idee des Piping mit
%>%
beschränkt sich nicht nur auf Datenrahmen und lässt sich leicht auf andere Kontexte verallgemeinern: interaktive Webgrafiken , Web Scraping , Kernel , Laufzeitverträge , ...)Speicher und Leistung
Ich habe diese zusammengefasst, weil sie für mich nicht so wichtig sind. Die meisten R-Benutzer arbeiten mit weit unter 1 Million Datenzeilen, und dplyr ist für diese Datengröße ausreichend schnell genug, um die Verarbeitungszeit nicht zu kennen. Wir optimieren dplyr auf Ausdruckskraft bei mittleren Daten. Fühlen Sie sich frei, data.table für die Rohgeschwindigkeit bei größeren Datenmengen zu verwenden.
Die Flexibilität von dplyr bedeutet auch, dass Sie die Leistungsmerkmale mit derselben Syntax problemlos anpassen können. Wenn die Leistung von dplyr mit dem Datenrahmen-Backend für Sie nicht gut genug ist, können Sie das data.table-Backend verwenden (allerdings mit etwas eingeschränkter Funktionalität). Wenn die Daten, mit denen Sie arbeiten, nicht in den Speicher passen, können Sie ein Datenbank-Backend verwenden.
Trotzdem wird die Leistung von dplyr langfristig besser. Wir werden auf jeden Fall einige der großartigen Ideen von data.table implementieren, z. B. die Radix-Bestellung und die Verwendung des gleichen Index für Joins und Filter. Wir arbeiten auch an der Parallelisierung, damit wir mehrere Kerne nutzen können.
Eigenschaften
Ein paar Dinge, an denen wir 2015 arbeiten wollen:
das
readr
Paket, um es einfach zu machen, Dateien von der Festplatte in den Speicher zu bekommen, analog zufread()
.Flexiblere Verknüpfungen, einschließlich Unterstützung für Nicht-Equi-Verknüpfungen.
Flexiblere Gruppierung wie Bootstrap-Beispiele, Rollups und mehr
Ich investiere auch Zeit in die Verbesserung der Datenbankkonnektoren von R , die Möglichkeit, mit Web-APIs zu kommunizieren und das Scrapen von HTML-Seiten zu vereinfachen .
quelle
data.table
Syntax selbst bevorzuge ), aber Sie können sie leicht verwenden,%>%
umdata.table
Operationen zu leiten , wenn Sie keinen[
Stil mögen .%>%
ist nicht spezifisch fürdplyr
, sondern stammt aus einem separaten Paket (von dem Sie zufällig auch Mitautor sind), daher bin ich mir nicht sicher, ob ich verstehe, was Sie in den meisten Abschnitten Ihres Syntax- Absatzes sagen wollen .%>%
mit data.table verwenden könnenDT[\n\texpression\n][\texpression\n]
( Kern ), was eigentlich ziemlich gut funktioniert. Ich behalte Aruns Antwort als Antwort, da er meine spezifischen Fragen, die weniger die Zugänglichkeit der Syntax betreffen, direkter beantwortet, aber ich denke, dies ist eine gute Antwort für Leute, die versuchen, ein allgemeines Gefühl für die Unterschiede / Gemeinsamkeiten zwischendplyr
und zu bekommendata.table
.fread()
? Wäre es nicht besser, Zeit für die Verbesserung von fread () oder die Arbeit an anderen (unterentwickelten) Dingen aufzuwenden?data.table
basiert auf einem massiven Missbrauch der[]
Notation. Das ist seine größte Stärke und seine größte Schwäche.In direkter Antwort auf den Fragentitel ...
dplyr
macht definitiv Dinge,data.table
die nicht können.Dein Punkt # 3
ist eine direkte Antwort auf Ihre eigene Frage, aber nicht hoch genug.
dplyr
ist wirklich ein erweiterbares Front-End für mehrere Datenspeichermechanismen, ebensodata.table
wie eine Erweiterung für einen einzelnen.Betrachten Sie es
dplyr
als eine agnostische Back-End-Schnittstelle, bei der alle Ziele dasselbe Grammatikprogramm verwenden, über das Sie die Ziele und Handler nach Belieben erweitern können.data.table
ist aus derdplyr
Perspektive eines dieser Ziele.Sie werden (ich hoffe) nie einen Tag sehen, an dem
data.table
versucht wird, Ihre Abfragen zu übersetzen, um SQL-Anweisungen zu erstellen, die mit Datenträgern auf der Festplatte oder im Netzwerk arbeiten.dplyr
kann möglicherweise Dinge tun,data.table
die nicht oder möglicherweise nicht so gut tun.Aufgrund des Entwurfs der Arbeit im Arbeitsspeicher
data.table
könnte es viel schwieriger sein, sich auf die parallele Verarbeitung von Abfragen auszudehnen alsdplyr
.Als Antwort auf die Fragen im Körper ...
Verwendungszweck
Dies mag wie ein Kahn erscheinen, aber die wirkliche Antwort ist nein. Personen, die mit Werkzeugen vertraut sind, scheinen entweder dasjenige zu verwenden, das ihnen am vertrautesten ist, oder dasjenige, das tatsächlich das richtige für den jeweiligen Job ist. Wenn dies gesagt ist, möchten Sie manchmal eine bestimmte Lesbarkeit, manchmal ein Leistungsniveau präsentieren, und wenn Sie ein ausreichend hohes Niveau von beiden benötigen, benötigen Sie möglicherweise nur ein anderes Werkzeug, um das zu tun, was Sie bereits benötigen, um klarere Abstraktionen zu erstellen .
Performance
Wieder nein.
data.table
zeichnet sich dadurch aus, dass es bei allem , was es tut , effizient ist, wenndplyr
die Last in gewisser Hinsicht auf den zugrunde liegenden Datenspeicher und die registrierten Handler beschränkt ist.Wenn Sie also auf ein Leistungsproblem stoßen
data.table
, können Sie ziemlich sicher sein, dass es in Ihrer Abfragefunktion enthalten ist. Wenn es sich tatsächlich um einen Engpass handeltdata.table
, haben Sie die Freude gewonnen, einen Bericht einzureichen. Dies gilt auch, wenndplyr
esdata.table
als Back-End verwendet wird. Möglicherweise sehen Sie einen gewissen Overhead,dplyr
aber wahrscheinlich ist es Ihre Anfrage.Wenn
dplyr
Leistungsprobleme mit Backends auftreten, können Sie diese umgehen, indem Sie eine Funktion für die Hybridauswertung registrieren oder (bei Datenbanken) die generierte Abfrage vor der Ausführung bearbeiten.Sehen Sie auch die akzeptierte Antwort auf wann ist plyr besser als data.table?
quelle