Soll ich meinen Lernaufwand für die Daten Gerangel in R, und zwar zwischen investieren dplyr
, dtplyr
und data.table
?
Ich benutze
dplyr
meistens, aber wenn die Daten dafür zu groß sind, werde ich sie verwendendata.table
, was selten vorkommt. Nun, dadtplyr
v1.0 als Schnittstelle für herauskommtdata.table
, scheint es, als müsste ich mir nie wieder Gedanken über die Verwendung derdata.table
Schnittstelle machen.Was sind die nützlichsten Funktionen oder Aspekte
data.table
, die derzeit nicht verwendet werden könnendtplyr
und mit denen dies wahrscheinlich nie geschehen wirddtplyr
?Auf
dplyr
den ersten Blickdata.table
klingt es so, als würdedtplyr
es überholendplyr
. Wird es einen Grund geben, es zu verwenden,dplyr
wenndtplyr
es vollständig ausgereift ist?
Hinweis: Ich frage nicht nach dplyr
vs data.table
(wie in data.table vs dplyr: Kann einer etwas gut machen, was der andere nicht kann oder schlecht macht? ), Aber da einer für ein bestimmtes Problem dem anderen vorgezogen wird, warum nicht? t dtplyr
das zu verwendende Werkzeug sein.
quelle
dplyr
dem du gut abschneiden kannst und in dem du nicht gut abschneiden kannstdata.table
? Wenn nicht, ist der Wechseldata.table
zu besser alsdtplyr
.dtplyr
Readme-Datei: „Einigedata.table
Ausdrücke haben keine direktedplyr
Entsprechung. Zum Beispiel gibt es keine Möglichkeit, Cross- oder Rolling-Joins mit auszudrückendplyr
. ' und 'Um derdplyr
Semantik zu entsprechen, wirdmutate
() standardmäßig nicht geändert. Dies bedeutet, dass die meisten Ausdrückemutate()
eine Kopie erstellen müssen, die beidata.table
direkter Verwendung nicht erforderlich wäre . ' Es gibt einen Weg um diesen zweiten Teil herum, aber wenn man bedenkt, wie oft ermutate
verwendet wird, ist das in meinen Augen ein ziemlich großer Nachteil.Antworten:
Ich werde versuchen, meine besten Anleitungen zu geben, aber es ist nicht einfach, weil man mit allen {data.table}, {dplyr}, {dtplyr} und auch {base R} vertraut sein muss. Ich benutze {data.table} und viele {tidy-world} -Pakete (außer {dplyr}). Ich liebe beide, obwohl ich die Syntax von data.table gegenüber dplyr's bevorzuge. Ich hoffe, dass alle Tidy-World-Pakete {dtplyr} oder {data.table} als Backend verwenden, wann immer dies erforderlich ist.
Wie bei jeder anderen Übersetzung (denken Sie an dplyr-to-sparkly / SQL) gibt es Dinge, die zumindest vorerst übersetzt werden können oder nicht. Ich meine, vielleicht kann {dtplyr} es eines Tages zu 100% übersetzen, wer weiß. Die folgende Liste ist weder vollständig noch zu 100% korrekt, da ich mein Bestes geben werde, um auf der Grundlage meines Wissens zu verwandten Themen / Paketen / Problemen / etc. Zu antworten.
Für die Antworten, die nicht ganz korrekt sind, hoffe ich, dass es Ihnen einige Anleitungen gibt, auf welche Aspekte von {data.table} Sie achten sollten, und vergleichen Sie sie mit {dtplyr} und finden Sie die Antworten selbst heraus. Nehmen Sie diese Antworten nicht als selbstverständlich an.
Und ich hoffe, dieser Beitrag kann als eine der Ressourcen für alle {dplyr}, {data.table} oder {dtplyr} Benutzer / Ersteller für Diskussionen und Kooperationen verwendet werden und #RStats noch besser machen.
{data.table} wird nicht nur für schnelle und speichereffiziente Operationen verwendet. Es gibt viele Leute, einschließlich mir, die die elegante Syntax von {data.table} bevorzugen. Es enthält auch andere schnelle Operationen wie Zeitreihenfunktionen wie
frollapply
die in C geschriebene Rolling-Family (dh ). Es kann mit allen Funktionen verwendet werden, einschließlich Tidyverse. Ich benutze {data.table} + {purrr} viel!Komplexität der Operationen
Dies kann leicht übersetzt werden
{data.table} ist sehr schnell und speichereffizient, da (fast?) alles von Grund auf von C mit den Schlüsselkonzepten Update-by-Reference erstellt wird , Key (Think SQL) und deren unermüdlicher Optimierung überall im Paket erstellt wird (dh
fifelse
,fread/fread
Radix - Sortierreihenfolge von Basis R angenommen), wobei er darauf achtete die Syntax ist präzise und konsistent, das ist , warum ich denke , es ist elegant ist.Von der Einführung in data.table werden die wichtigsten Datenmanipulationsvorgänge wie Teilmenge, Gruppe, Aktualisierung, Verknüpfung usw. für zusammengehalten
prägnante und konsistente Syntax ...
flüssige Analyse ohne die kognitive Belastung, jede Operation abbilden zu müssen ...
Automatische und sehr effektive Optimierung von Vorgängen durch genaue Kenntnis der für jeden Vorgang erforderlichen Daten, was zu einem sehr schnellen und speichereffizienten Code führt
Der letzte Punkt als Beispiel:
Um die Vorteile von {data.table} nutzen zu können, muss die Übersetzung von {dtplr} in dieser Hinsicht korrekt sein. Je komplexer die Operationen sind, desto schwieriger sind die Übersetzungen. Für einfache Operationen wie oben kann es sicherlich leicht übersetzt werden. Für komplexe oder solche, die nicht von {dtplyr} unterstützt werden, müssen Sie sich wie oben erwähnt selbst herausfinden, die übersetzte Syntax und den Benchmark vergleichen und vertraute verwandte Pakete kennen.
Für komplexe oder nicht unterstützte Operationen kann ich im Folgenden einige Beispiele nennen. Wieder versuche ich nur mein Bestes. Sei sanft zu mir.
Update-by-Reference
Ich werde nicht auf das Intro / die Details eingehen, aber hier sind einige Links
Hauptressource: Referenzsemantik
Weitere Details: Genau verstehen, wann eine data.table auf eine andere data.table verweist (im Vergleich zu einer Kopie davon)
Update-by-Reference ist meiner Meinung nach das wichtigste Merkmal von {data.table} und das macht es so schnell und speichereffizient.
dplyr::mutate
unterstützt es standardmäßig nicht. Da ich mit {dtplyr} nicht vertraut bin, bin ich mir nicht sicher, wie viel und welche Vorgänge von {dtplyr} unterstützt werden können oder nicht. Wie oben erwähnt, hängt dies auch von der Komplexität der Operationen ab, die sich wiederum auf die Übersetzungen auswirken.Es gibt zwei Möglichkeiten, Update-by-Reference in {data.table} zu verwenden
Zuweisungsoperator von {data.table}
:=
set
-Familie:set
,setnames
,setcolorder
,setkey
,setDT
,fsetdiff
, und viele mehr:=
wird im Vergleich zu häufiger verwendetset
. Bei komplexen und großen Datenmengen durch Referenz aktualisieren der Schlüssel, um Höchstgeschwindigkeit und Speichereffizienz zu erzielen. Die einfache Denkweise (nicht 100% genau, da die Details viel komplizierter sind, da es sich um Hard- / Flachkopien und viele andere Faktoren handelt) besagt, dass es sich um einen großen Datensatz von 10 GB mit 10 Spalten und jeweils 1 GB handelt . Um eine Spalte zu bearbeiten, müssen Sie nur 1 GB verarbeiten.Der entscheidende Punkt ist, dass Sie mit Update-by-Reference nur die erforderlichen Daten verarbeiten müssen. Aus diesem Grund verwenden wir bei der Verwendung von {data.table}, insbesondere bei großen Datenmengen, nach Möglichkeit immer die Aktualisierung per Referenz . Beispiel: Bearbeiten eines großen Modellierungsdatensatzes
Der Verschachtelungsvorgang wird
list(.SD)
möglicherweise von {dtlyr} nicht unterstützt, wenn tidyverse Benutzertidyr::nest
? Ich bin mir also nicht sicher, ob die nachfolgenden Operationen so übersetzt werden können, dass {data.table} schneller und weniger Speicherplatz ist.HINWEIS: Das Ergebnis von data.table ist in "Millisekunde", dplyr in "Minute".
Es gibt viele Anwendungsfälle von Update-by-Reference und selbst {data.table} -Benutzer verwenden die erweiterte Version nicht immer, da mehr Codes erforderlich sind. Ob {dtplyr} diese Out-of-the-Box unterstützt, müssen Sie selbst herausfinden.
Mehrere Referenzaktualisierungen für dieselben Funktionen
Hauptressource : Elegantes Zuweisen mehrerer Spalten in data.table mit lapply ()
Dies betrifft entweder die am häufigsten verwendete
:=
oderset
.Laut Ersteller von {data.table} Matt Dowle
Join + Setkey + Update-by-Reference
Ich brauchte in letzter Zeit eine schnelle Verknüpfung mit relativ großen Datenmengen und ähnlichen Verknüpfungsmustern, daher verwende ich anstelle der normalen Verknüpfungen die Möglichkeit, durch Referenz zu aktualisieren . Da sie mehr Codes benötigen, verpacke ich sie in ein privates Paket mit einer nicht standardmäßigen Bewertung für Wiederverwendbarkeit und Lesbarkeit, wo ich es nenne
setjoin
.Ich habe hier einen Benchmark durchgeführt: data.table join + update-by-reference + setkey
Zusammenfassung
HINWEIS:
dplyr::left_join
wurde ebenfalls getestet und ist mit ~ 9.000 ms am langsamsten. Verwenden Sie mehr Speicher als beide {data.table}update_by_reference
undsetkey_n_update
, aber weniger Speicher als den normalen_join von {data.table}. Es verbrauchte ungefähr ~ 2,0 GB Speicher. Ich habe es nicht aufgenommen, da ich mich ausschließlich auf {data.table} konzentrieren möchte.Wichtigste Ergebnisse
setkey + update
undupdate
sind ~ 11 und ~ 6,5 - mal schneller alsnormal join
jeweilssetkey + update
ähnelt die Performance von demupdate
Overhead, dersetkey
die eigenen Performancegewinne weitgehend ausgleichtsetkey
nicht erforderlich,setkey + update
schneller als dasupdate
~ 1,8-fache (oder schneller als dasnormal join
~ 11-fache)Beispiele
Verwenden Sie für performante und speichereffiziente Verknüpfungen entweder
update
odersetkey + update
, wenn letzteres auf Kosten von mehr Codes schneller ist.Der Kürze halber sehen wir uns einige Pseudocodes an . Die Logik ist die gleiche.
Für eine oder mehrere Spalten
Für viele Spalten
Wrapper für schnelle und speichereffiziente Verknüpfungen ... viele von ihnen ... mit ähnlichem Verknüpfungsmuster, wickeln Sie sie wie
setjoin
oben - mitupdate
- mit oder ohnesetkey
Mit
setkey
Argumenton
weggelassen werden. Es kann auch zur besseren Lesbarkeit enthalten sein, insbesondere für die Zusammenarbeit mit anderen.Große Reihenoperation
set
setkey
)Verwandte Ressource: Fügen Sie am Ende eines data.table-Objekts eine Zeile als Referenz hinzu
Zusammenfassung der Aktualisierung durch Referenz
Dies sind nur einige Anwendungsfälle von Update-by-Reference . Es gibt viele mehr.
Wie Sie sehen können, gibt es für die erweiterte Verwendung des Umgangs mit großen Datenmengen viele Anwendungsfälle und -techniken, bei denen Update-by-Reference verwendet wird für große Datenmengen verwendet wird. Es ist nicht so einfach in {data.table} zu verwenden und ob {dtplyr} es unterstützt, können Sie selbst herausfinden.
Ich konzentriere mich auf Update-by-Reference in diesem Beitrag da ich denke, dass dies die leistungsstärkste Funktion von {data.table} für schnelle und speichereffiziente Vorgänge ist. Das heißt, es gibt viele, viele andere Aspekte, die es auch so effizient machen, und ich denke, die von {dtplyr} nicht nativ unterstützt werden.
Andere Schlüsselaspekte
Was unterstützt wird / nicht, hängt auch von der Komplexität der Vorgänge ab und davon, ob es sich um die native Funktion von data.table handelt, z. B. Update-by-Reference oder
setkey
. Und ob der übersetzte Code der effizientere ist (einer, den Benutzer von data.table schreiben würden), ist auch ein weiterer Faktor (dh der Code wird übersetzt, aber ist es die effiziente Version?). Viele Dinge sind miteinander verbunden.setkey
. Siehe Schlüssel und schnelle Teilmenge der binären Suchefrollapply
. Walzfunktionen, Walzaggregate, Schiebefenster, gleitender Durchschnitti
,j
oderby
Operationen (können Sie fast alle Ausdrücke dort verwenden), ich denke , die die Übersetzungen härter, vor allem wenn es mit kombinieren Update-by-reference ,setkey
und anderen einheimischen data.table funktioniert wiefrollapply
stringr::str_*
Funktionen von Familie und Basis R, und ich finde, dass Basis R bis zu einem gewissen Grad schneller ist, und verwende diese. Der Punkt ist, halten Sie sich nicht nur an tidyverse oder data.table oder ..., sondern erkunden Sie andere Optionen, um die Arbeit zu erledigen.Viele dieser Aspekte hängen mit den oben genannten Punkten zusammen
Komplexität der Operationen
Update-by-Reference
Sie können herausfinden, ob {dtplyr} diese Vorgänge unterstützt, insbesondere wenn sie kombiniert werden.
Ein weiterer nützlicher Trick beim Umgang mit kleinen oder großen Datenmengen während einer interaktiven Sitzung: {data.table} erfüllt wirklich das Versprechen, die Programmier- und Rechenzeit enorm zu reduzieren .
Einstellschlüssel für wiederholt verwendete Variablen für Geschwindigkeit und 'aufgeladene Rownamen' (Teilmenge ohne Angabe des Variablennamens).
Wenn Ihre Operationen nur einfache wie im ersten Beispiel umfassen, kann {dtplyr} die Aufgabe erledigen. Für komplexe / nicht unterstützte können Sie dieses Handbuch verwenden, um die übersetzten von {dtplyr} damit zu vergleichen, wie erfahrene data.table-Benutzer mit der eleganten Syntax von data.table schnell und speichereffizient codieren würden. Die Übersetzung bedeutet nicht, dass dies der effizienteste Weg ist, da es möglicherweise unterschiedliche Techniken gibt, um mit unterschiedlichen Fällen großer Datenmengen umzugehen. Für noch größere Datenmengen können Sie {data.table} mit {disk.frame} , {fst} und {drake} und anderen fantastischen Paketen kombinieren , um das Beste daraus zu machen. Es gibt auch eine {big.data.table} , die derzeit jedoch inaktiv ist.
Ich hoffe es hilft allen. Einen schönen Tag noch ☺☺
quelle
Nicht-Equi-Joins und Rolling-Joins kommen in den Sinn. Es scheint keine Pläne zu geben, überhaupt äquivalente Funktionen in dplyr aufzunehmen, daher gibt es für dtplyr nichts zu übersetzen.
Es gibt auch eine Umformung (optimierter Dcast und Schmelze, die den gleichen Funktionen in reshape2 entspricht), die nicht auch in dplyr enthalten ist.
Alle * _if- und * _at-Funktionen können derzeit nicht mit dtplyr übersetzt werden, aber diese sind in Arbeit.
quelle
Aktualisieren einer Spalte beim Beitritt Einige .SD-Tricks Viele f-Funktionen Und Gott weiß was noch, denn #rdatatable ist mehr als nur eine einfache Bibliothek und kann nicht mit wenigen Funktionen zusammengefasst werden
Es ist ein ganzes Ökosystem für sich
Ich habe dplyr seit dem Tag, an dem ich mit R angefangen habe, nie mehr gebraucht. Weil data.table so verdammt gut ist
quelle