Aperçu
Je suis relativement familier data.table
, pas tellement dplyr
. J'ai lu quelques dplyr
vignettes et exemples qui ont surgi sur SO, et jusqu'à présent, mes conclusions sont les suivantes:
data.table
etdplyr
sont comparables en vitesse, sauf lorsqu'il existe de nombreux groupes (c.-à-d.> 10-100K) et dans certaines autres circonstances (voir les repères ci-dessous)dplyr
a une syntaxe plus accessibledplyr
résume (ou fera) les interactions DB potentielles- Il y a quelques différences de fonctionnalités mineures (voir "Exemples / Utilisation" ci-dessous)
Dans mon esprit, 2. n'a pas beaucoup de poids car je le connais assez bien data.table
, même si je comprends que pour les utilisateurs novices, ce sera un facteur important. Je voudrais éviter un argument qui est plus intuitif, car cela n'est pas pertinent pour ma question spécifique posée du point de vue de quelqu'un qui est déjà familier data.table
. Je voudrais également éviter une discussion sur la façon dont "plus intuitif" conduit à une analyse plus rapide (certainement vrai, mais encore une fois, pas ce qui m'intéresse le plus ici).
Question
Ce que je veux savoir c'est:
- Y a-t-il des tâches analytiques qui sont beaucoup plus faciles à coder avec l'un ou l'autre package pour les personnes familières avec les packages (c'est-à-dire une combinaison de touches requise par rapport au niveau requis d'ésotérisme, où moins de chacun est une bonne chose).
- Existe-t-il des tâches analytiques qui sont exécutées de manière substantielle (c'est-à-dire plus de 2x) plus efficacement dans un package par rapport à un autre?
Une question récente sur les SO m'a fait réfléchir un peu plus, car jusqu'à ce moment-là, je ne pensais pas dplyr
offrir beaucoup plus que ce que je pouvais déjà faire data.table
. Voici la dplyr
solution (données en fin de Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Ce qui était bien mieux que ma tentative de piratage pour data.table
trouver une solution. Cela dit, les bonnes data.table
solutions sont également assez bonnes (merci Jean-Robert, Arun, et notez ici que j'ai préféré une seule déclaration à la solution strictement la plus optimale):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
La syntaxe de ce dernier peut sembler très ésotérique, mais elle est en fait assez simple si vous en avez l'habitude data.table
(c'est- à -dire qu'elle n'utilise pas certaines des astuces les plus ésotériques).
Idéalement, ce que j'aimerais voir, ce sont de bons exemples où la manière dplyr
ou data.table
est beaucoup plus concise ou fonctionne beaucoup mieux.
Exemples
Usagedplyr
ne permet pas les opérations groupées qui retournent un nombre arbitraire de lignes (à partir de la question d' eddi , remarque: cela semble être implémenté dans dplyr 0.5 , également, @beginneR montre une solution de contournement potentielle à utiliserdo
dans la réponse à la question de @ eddi).data.table
prend en charge les jointures roulantes (merci @dholstius) ainsi que les jointures à chevauchementdata.table
optimise en interne les expressions du formulaireDT[col == value]
ouDT[col %in% values]
pour la vitesse grâce à l'indexation automatique qui utilise la recherche binaire tout en utilisant la même syntaxe de base R. Voir ici pour plus de détails et une petite référence.dplyr
offre des versions d'évaluation standard de fonctions (par exempleregroup
,summarize_each_
) qui peuvent simplifier l'utilisation programmatique dedplyr
(notez que l'utilisation programmatique dedata.table
est certainement possible, nécessite juste une réflexion, une substitution / citation, etc., au moins à ma connaissance)
- J'ai exécuté mes propres tests de performance et j'ai trouvé que les deux packages étaient comparables dans l'analyse de style "split apply combine", sauf quand il y a un très grand nombre de groupes (> 100K) à quel point
data.table
devient considérablement plus rapide. - @Arun a exécuté des tests de performance sur les jointures , montrant que les
data.table
échelles sont meilleures quedplyr
lorsque le nombre de groupes augmente (mis à jour avec les améliorations récentes des packages et de la version récente de R). En outre, une référence lors de la tentative d'obtention de valeurs uniques estdata.table
environ 6 fois plus rapide. - (Non vérifié) a
data.table
75% plus rapide sur les versions plus grandes d'un groupe / appliquer / trier tandis qu'ildplyr
était 40% plus rapide sur les plus petites ( une autre question SO des commentaires , merci danas). - Matt, l'auteur principal de
data.table
, a benchmarkée des opérations de regroupement surdata.table
,dplyr
et pythonpandas
sur un maximum de 2 milliards de lignes (~ 100 Go en RAM) . - Une référence plus ancienne sur les groupes 80K a
data.table
~ 8 fois plus rapide
Les données
Ceci est le premier exemple que j'ai montré dans la section des questions.
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))
la source
dplyr
ci est:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]
dplyr
et lesdata.table
équipes travaillent sur des repères, donc une réponse sera là à un moment donné. # 2 (syntaxe) imO est strictement faux, mais cela s'aventure clairement en territoire d'opinion, donc je vote pour fermer aussi.(d)plyr
a la mesure 0dplyr
etplyr
en ce qui concerne la syntaxe et est fondamentalement la principale raison pour laquelle je n'aime pas leur syntaxe, est que je dois apprendre beaucoup trop (lire plus de 1) des fonctions supplémentaires (avec des noms qui encore ça n'a pas de sens pour moi), rappelez-vous ce qu'ils font, quels arguments ils soutiennent, etc..SD
). [sérieusement] Je pense que ce sont des différences de conception légitimes quiRéponses:
Nous devons couvrir au moins ces aspects pour fournir une réponse complète / comparaison (sans ordre d'importance):
Speed
,Memory usage
,Syntax
etFeatures
.Mon intention est de couvrir chacun de ces éléments aussi clairement que possible du point de vue data.table.
La syntaxe data.table est cohérente dans sa forme -
DT[i, j, by]
. Garderi
,j
etby
ensemble, c'est par la conception. En gardant les opérations liées ensemble, il permet d' optimiser facilement les opérations pour la vitesse et surtout l' utilisation de la mémoire , et fournit également des fonctionnalités puissantes , tout en maintenant la cohérence de la syntaxe.1. Vitesse
Un certain nombre de références (bien que principalement sur les opérations de regroupement) ont été ajoutées à la question montrant déjà data.table devient plus rapide que dplyr lorsque le nombre de groupes et / ou de lignes à regrouper augmente, y compris les références de Matt sur le regroupement de 10 millions à 2 milliards de lignes (100 Go de RAM) sur 100 à 10 millions de groupes et différentes colonnes de regroupement, ce qui se compare également
pandas
. Voir également les repères mis à jour , qui incluentSpark
etpydatatable
également.Concernant les repères, il serait intéressant de couvrir également ces aspects restants:
Opérations de regroupement impliquant un sous - ensemble de lignes , c'est-à-dire
DT[x > val, sum(y), by = z]
opérations de type.Comparez d'autres opérations telles que la mise à jour et les jointures .
Évaluez également l' empreinte mémoire pour chaque opération en plus de l'exécution.
2. Utilisation de la mémoire
Les opérations impliquant
filter()
ouslice()
dans dplyr peuvent être inefficaces en mémoire (à la fois sur data.frames et data.tables). Voir cet article .L'interface data.table permet actuellement de modifier / mettre à jour les colonnes par référence (notez que nous n'avons pas besoin de réaffecter le résultat à une variable).
Mais dplyr ne mettra jamais à jour par référence. L'équivalent dplyr serait (notez que le résultat doit être réaffecté):
Une préoccupation à cet égard est la transparence référentielle . La mise à jour d'un objet data.table par référence, en particulier au sein d'une fonction, n'est pas toujours souhaitable. Mais c'est une fonctionnalité incroyablement utile: consultez ceci et ces articles pour des cas intéressants. Et nous voulons le garder.
Par conséquent, nous travaillons à l'exportation de la
shallow()
fonction dans data.table qui fournira à l'utilisateur les deux possibilités . Par exemple, s'il est souhaitable de ne pas modifier le data.table d'entrée dans une fonction, on peut alors faire:En ne l'utilisant pas
shallow()
, l'ancienne fonctionnalité est conservée:En créant une copie superficielle à l' aide de
shallow()
, nous comprenons que vous ne souhaitez pas modifier l'objet d'origine. Nous nous occupons de tout en interne pour nous assurer que tout en veillant à ne copier les colonnes que vous les modifiez uniquement lorsque cela est absolument nécessaire . Une fois implémenté, cela devrait régler complètement le problème de transparence référentielle tout en offrant à l'utilisateur les deux possibilités.Agréger lors de l'adhésion:
Supposons que vous ayez deux tableaux de données comme suit:
Et vous souhaitez obtenir
sum(z) * mul
pour chaque ligneDT2
tout en se joignant par des colonnesx,y
. On peut soit:1) agréger
DT1
pour obtenirsum(z)
, 2) effectuer une jointure et 3) multiplier (ou)2) tout faire en une seule fois (en utilisant la
by = .EACHI
fonction):Quel est l'avantage?
Nous n'avons pas à allouer de mémoire pour le résultat intermédiaire.
Nous n'avons pas à grouper / hacher deux fois (un pour l'agrégation et l'autre pour la jonction).
Et plus important encore, l'opération que nous voulions effectuer est claire en regardant
j
dans (2).Consultez cet article pour une explication détaillée de
by = .EACHI
. Aucun résultat intermédiaire n'est matérialisé et la jointure + agrégat est effectuée en une seule fois.Jetez un œil à ceci , ceci et cela pour des scénarios d'utilisation réels.
En
dplyr
vous devez rejoindre et agréger ou agréger d'abord, puis rejoindre , aucun des deux n'est aussi efficace, en termes de mémoire (ce qui se traduit à son tour par la vitesse).Mise à jour et jointures:
Considérez le code data.table ci-dessous:
ajoute / met à jour
DT1
la colonnecol
avec àmul
partir deDT2
sur les lignes oùDT2
la colonne clé correspondDT1
. Je ne pense pas qu'il y ait un équivalent exact de cette opération dansdplyr
, c'est- à -dire sans éviter une*_join
opération, qui devrait copier l'intégralitéDT1
juste pour y ajouter une nouvelle colonne, ce qui est inutile.Consultez ce post pour un scénario d'utilisation réel.
3. Syntaxe
Regardons maintenant la syntaxe . Hadley a commenté ici :
Je trouve cette remarque inutile car elle est très subjective. Ce que nous pouvons peut-être essayer, c'est de contraster la cohérence syntaxique . Nous comparerons côte à côte data.table et dplyr syntax.
Nous travaillerons avec les données fictives ci-dessous:
Opérations d'agrégation / mise à jour de base.
La syntaxe data.table est compacte et dplyr est assez verbeuse. Les choses sont plus ou moins équivalentes dans le cas (a).
Dans le cas (b), nous avons dû utiliser
filter()
dans dplyr tout en résumant . Mais lors de la mise à jour , nous avons dû déplacer la logique à l'intérieurmutate()
. Dans data.table cependant, nous exprimons les deux opérations avec la même logique - opérons sur les lignes oùx > 2
, mais dans le premier cas, obtiennentsum(y)
, alors que dans le second cas mettez à jour ces lignes poury
avec sa somme cumulée.C'est ce que nous voulons dire lorsque nous disons que le
DT[i, j, by]
formulaire est cohérent .De même, dans le cas (c), lorsque nous avons une
if-else
condition, nous pouvons exprimer la logique "telle quelle " dans data.table et dplyr. Cependant, si nous voulons retourner uniquement les lignes où laif
condition satisfait et ignorer le contraire, nous ne pouvons pas utilisersummarise()
directement (AFAICT). Nous devons d'filter()
abord et ensuite résumer carsummarise()
attend toujours une seule valeur .Bien qu'elle renvoie le même résultat, l'utilisation
filter()
ici rend l'opération réelle moins évidente.Il pourrait très bien être possible d'utiliser
filter()
dans le premier cas également (cela ne me semble pas évident), mais mon point est que nous ne devrions pas avoir à le faire.Agrégation / mise à jour sur plusieurs colonnes
Dans le cas (a), les codes sont plus ou moins équivalents. data.table utilise une fonction de base familière
lapply()
, tandis quedplyr
introduit*_each()
avec un tas de fonctionsfuns()
.data.table
:=
nécessite que les noms de colonne soient fournis, tandis que dplyr le génère automatiquement.Dans le cas (b), la syntaxe de dplyr est relativement simple. L'amélioration des agrégations / mises à jour sur plusieurs fonctions est sur la liste de data.table.
Dans le cas (c) cependant, dplyr retournerait
n()
autant de fois que de colonnes, au lieu d'une seule fois. Dans data.table, tout ce que nous devons faire est de renvoyer une listej
. Chaque élément de la liste deviendra une colonne dans le résultat. Donc, nous pouvons utiliser, encore une fois, la fonction de base familièrec()
pour concaténer.N
à unlist
qui retourne alist
.Rejoint
dplyr fournit des fonctions distinctes pour chaque type de jointure où data.table autorise les jointures en utilisant la même syntaxe
DT[i, j, by]
(et avec raison). Il fournit également unemerge.data.table()
fonction équivalente comme alternative.Certains pourraient trouver une fonction distincte pour chaque jointure beaucoup plus agréable (gauche, droite, intérieure, anti, semi, etc.), tandis que d'autres pourraient aimer data.table
DT[i, j, by]
, oumerge()
qui est similaire à la base R.Cependant, dplyr rejoint exactement cela. Rien de plus. Rien de moins.
data.tables peut sélectionner des colonnes lors de la jointure (2), et dans dplyr, vous devrez d'
select()
abord sur les deux data.frames avant de rejoindre comme indiqué ci-dessus. Sinon, vous matérialiserez la jointure avec des colonnes inutiles pour les supprimer plus tard, ce qui est inefficace.data.tables peut s'agréger lors de la jointure (3) et également se mettre à jour lors de la jointure (4), en utilisant la
by = .EACHI
fonction. Pourquoi matérialiser l'intégralité du résultat de la jointure pour ajouter / mettre à jour seulement quelques colonnes?data.table est capable de faire rouler les jointures (5) - rouler en avant, LOCF , rouler en arrière, NOCB , le plus proche .
data.table a également un
mult =
argument qui sélectionne la première , la dernière ou toutes les correspondances (6).data.table a un
allow.cartesian = TRUE
argument pour se protéger des jointures invalides accidentelles.do()
...Le résumé de dplyr est spécialement conçu pour les fonctions qui renvoient une seule valeur. Si votre fonction renvoie des valeurs multiples / inégales, vous devrez recourir à
do()
. Vous devez connaître à l'avance toutes les valeurs de retour de vos fonctions..SD
l'équivalent est.
Dans data.table, vous pouvez jeter à peu près n'importe quoi
j
- la seule chose à retenir est qu'il retourne une liste afin que chaque élément de la liste soit converti en colonne.Dans dplyr, je ne peux pas faire ça. Vous devez recourir à la
do()
façon dont vous êtes sûr de savoir si votre fonction retournera toujours une seule valeur. Et c'est assez lent.Jetez un oeil à cette question SO et celle-ci . Je me demande s'il serait possible d'exprimer la réponse comme simple en utilisant la syntaxe de dplyr ...
4. Caractéristiques
J'ai souligné la plupart des fonctionnalités ici et aussi dans ce post. En plus:
fread - le lecteur de fichiers rapide est disponible depuis longtemps.
fwrite - un rédacteur de fichiers rapide parallélisé est maintenant disponible. Voir cet article pour une explication détaillée sur la mise en œuvre et # 1664 pour garder une trace des développements ultérieurs.
Indexation automatique - une autre fonctionnalité pratique pour optimiser la syntaxe de base R telle quelle, en interne.
Regroupement ad hoc :
dplyr
trie automatiquement les résultats en regroupant les variables pendantsummarise()
, ce qui n'est pas toujours souhaitable.De nombreux avantages dans les jointures data.table (pour la vitesse / l'efficacité de la mémoire et la syntaxe) mentionnés ci-dessus.
<=, <, >, >=
Jointures non équi : Permet les jointures utilisant d'autres opérateurs ainsi que tous les autres avantages des jointures data.table.Des jointures de plage superposées ont été récemment implémentées dans data.table. Consultez cet article pour un aperçu des repères.
setorder()
fonction dans data.table qui permet une réorganisation très rapide des data.tables par référence.dplyr fournit une interface vers des bases de données utilisant la même syntaxe, ce que data.table n'a pas pour le moment.
data.table
fournit des équivalents plus rapides des opérations réglées (écrit par Jan Gorecki) -fsetdiff
,fintersect
,funion
etfsetequal
avec plusall
argument (comme dans SQL).data.table se charge proprement sans avertissement de masquage et dispose d'un mécanisme décrit ici pour la
[.data.frame
compatibilité lorsqu'il est transmis à n'importe quel package R. dplyr modifie les fonctions de basefilter
,lag
et[
qui peuvent causer des problèmes; par exemple ici et ici .Finalement:
Sur les bases de données - il n'y a aucune raison pour que data.table ne puisse pas fournir une interface similaire, mais ce n'est pas une priorité maintenant. Il pourrait être bousculé si les utilisateurs aimeraient beaucoup cette fonctionnalité. Je ne sais pas.
Sur le parallélisme - Tout est difficile, jusqu'à ce que quelqu'un aille de l'avant et le fasse. Bien sûr, cela demandera des efforts (en étant thread-safe).
OpenMP
.la source
:=
), l'dplyr
équivalent devrait également être utilisé<-
comme auDF <- DF %>% mutate...
lieu de simplementDF %>% mutate...
dplyr
peut être plus facile pour les utilisateurs qui utilisaient laplyr
syntaxe, maisdata.table
peut être plus facile pour les utilisateurs qui ont utilisé pour interroger la syntaxe des langues commeSQL
, et l'algèbre relationnelle derrière elle, qui concerne la transformation des données tabulaires. @Arun, vous devez noter que les opérateurs de set sont très faciles à faire en enveloppant ladata.table
fonction et apportent bien sûr une accélération significative.Voici ma tentative d'une réponse complète du point de vue de dplyr, en suivant les grandes lignes de la réponse d'Arun (mais quelque peu réarrangé en fonction de priorités différentes).
Syntaxe
Il y a une certaine subjectivité dans la syntaxe, mais je maintiens mon affirmation selon laquelle la concision de data.table rend plus difficile à apprendre et à lire. C'est en partie parce que dplyr résout un problème beaucoup plus facile!
Une chose vraiment importante que dplyr fait pour vous, c'est qu'elle limite vos options. Je prétends que la plupart des problèmes de table unique peuvent être résolus avec seulement cinq verbes clés filtrer, sélectionner, muter, organiser et résumer, ainsi qu'un adverbe "par groupe". Cette contrainte est d'une grande aide lorsque vous apprenez la manipulation de données, car elle vous aide à réfléchir à votre problème. Dans dplyr, chacun de ces verbes est associé à une seule fonction. Chaque fonction fait un travail et est facile à comprendre isolément.
Vous créez de la complexité en canalisant ces opérations simples avec
%>%
. Voici un exemple de l'un des messages liés à Arun :Même si vous n'avez jamais vu dplyr auparavant (ou même R!), Vous pouvez toujours obtenir l'essentiel de ce qui se passe car les fonctions sont tous des verbes anglais. L'inconvénient des verbes anglais est qu'ils nécessitent plus de dactylographie que
[
, mais je pense que cela peut être largement atténué par une meilleure saisie semi-automatique.Voici le code data.table équivalent:
Il est plus difficile de suivre ce code à moins que vous ne soyez déjà familier avec data.table. (Je ne pouvais pas non plus comprendre comment mettre en retrait le répété
[
d'une manière qui me semble bonne). Personnellement, quand je regarde le code que j'ai écrit il y a 6 mois, c'est comme regarder un code écrit par un inconnu, donc j'en suis venu à préférer un code simple, mais verbeux.Deux autres facteurs mineurs qui, à mon avis, réduisent légèrement la lisibilité:
Étant donné que presque toutes les opérations de table de données utilisent,
[
vous avez besoin d'un contexte supplémentaire pour comprendre ce qui se passe. Par exemple,x[y]
joindre deux tables de données ou extraire des colonnes d'un bloc de données? Ce n'est qu'un petit problème, car dans un code bien écrit, les noms de variables devraient suggérer ce qui se passe.J'aime que
group_by()
c'est une opération distincte dans dplyr. Cela change fondamentalement le calcul, donc je pense que cela devrait être évident lors de l'écrémage du code, et c'est plus facile à repérergroup_by()
que l'by
argument[.data.table
.J'aime aussi que le tuyau ne se limite pas à un seul paquet. Vous pouvez commencer par ranger vos données avec tidyr et terminer avec un tracé dans ggvis . Et vous n'êtes pas limité aux packages que j'écris - n'importe qui peut écrire une fonction qui fait partie intégrante d'un canal de manipulation de données. En fait, je préfère plutôt le code data.table précédent réécrit avec
%>%
:Et l'idée de canaliser avec
%>%
ne se limite pas aux seules trames de données et est facilement généralisée à d'autres contextes: graphiques web interactifs , scraping web , gists , contrats d'exécution , ...)Mémoire et performances
Je les ai regroupés, car, pour moi, ils ne sont pas si importants. La plupart des utilisateurs R travaillent avec bien moins d'un million de lignes de données, et dplyr est suffisamment rapide pour cette taille de données que vous ne connaissez pas le temps de traitement. Nous optimisons dplyr pour l'expressivité sur les données moyennes; n'hésitez pas à utiliser data.table pour une vitesse brute sur des données plus volumineuses.
La flexibilité de dplyr signifie également que vous pouvez facilement modifier les caractéristiques de performance en utilisant la même syntaxe. Si les performances de dplyr avec le backend de trame de données ne vous conviennent pas, vous pouvez utiliser le backend de data.table (bien qu'avec un ensemble de fonctionnalités quelque peu restreint). Si les données avec lesquelles vous travaillez ne tiennent pas en mémoire, vous pouvez utiliser un backend de base de données.
Cela dit, les performances de dplyr s'amélioreront à long terme. Nous allons certainement implémenter certaines des grandes idées de data.table comme la commande radix et l'utilisation du même index pour les jointures et les filtres. Nous travaillons également sur la parallélisation afin de pouvoir profiter de plusieurs cœurs.
Caractéristiques
Quelques points sur lesquels nous prévoyons de travailler en 2015:
le
readr
package, pour faciliter la récupération des fichiers du disque et dans la mémoire, de manière analogue àfread()
.Jointures plus flexibles, y compris la prise en charge des jointures non équi.
Regroupement plus flexible comme des échantillons bootstrap, des rollups et plus
J'investis également du temps dans l'amélioration des connecteurs de base de données de R , la possibilité de parler aux API Web et de faciliter le raclage des pages html .
la source
data.table
syntaxe moi-même), mais vous pouvez facilement l'utiliser%>%
pour diriger lesdata.table
opérations si vous n'aimez pas le[
style.%>%
n'est pas spécifique àdplyr
, mais provient plutôt d'un package séparé (dont vous êtes également le co-auteur), donc je ne suis pas sûr de comprendre ce que vous essayez de dire dans la plupart de votre paragraphe de syntaxe .%>%
avec data.tableDT[\n\texpression\n][\texpression\n]
( gist ) qui fonctionne vraiment bien. Je garde la réponse d'Arun comme réponse car il répond plus directement à mes questions spécifiques qui ne concernent pas tellement l'accessibilité de la syntaxe, mais je pense que c'est une bonne réponse pour les personnes qui essaient d'avoir une idée générale des différences / similitudes entredplyr
etdata.table
.fread()
? Le temps ne serait-il pas mieux consacré à améliorer fread () ou à travailler sur d'autres choses (sous-développées)?data.table
est fondée sur un abus massif de la[]
notation. C'est sa plus grande force et sa plus grande faiblesse.En réponse directe au titre de la question ...
dplyr
fait définitivement des choses quidata.table
ne peuvent pas.Votre point # 3
est une réponse directe à votre propre question mais n'est pas élevée à un niveau suffisamment élevé.
dplyr
est véritablement un frontal extensible à plusieurs mécanismes de stockage de données, tout commedata.table
une extension à un seul.Regardez
dplyr
comme une interface agnostique dorsale, avec toutes les cibles utilisant la même grammaire, où vous pouvez étendre les cibles et les gestionnaires à volonté.data.table
est, dudplyr
point de vue, l'un de ces objectifs.Vous ne verrez jamais (j'espère) un jour qui
data.table
tentera de traduire vos requêtes pour créer des instructions SQL qui fonctionnent avec des magasins de données sur disque ou en réseau.dplyr
peut éventuellement faire les choses nedata.table
sera pas ou pourrait ne pas faire aussi bien.Basé sur la conception du travail en mémoire, il
data.table
pourrait être beaucoup plus difficile de s'étendre au traitement parallèle des requêtesdplyr
.En réponse aux questions internes ...
Usage
Cela peut sembler un coup de volée, mais la vraie réponse est non. Les personnes familiarisées avec les outils semblent utiliser celle qui leur est la plus familière ou celle qui est en fait la bonne pour le travail à accomplir. Cela étant dit, parfois vous voulez présenter une lisibilité particulière, parfois un niveau de performance, et lorsque vous avez besoin d'un niveau suffisamment élevé des deux, vous pouvez simplement avoir besoin d'un autre outil pour accompagner ce que vous avez déjà pour rendre les abstractions plus claires .
Performance
Encore une fois, non.
data.table
excelle à être efficace dans tout ce qu'il fait, oùdplyr
se trouve le fardeau d'être limité à certains égards au magasin de données sous-jacent et aux gestionnaires enregistrés.Cela signifie que lorsque vous rencontrez un problème de performances avec,
data.table
vous pouvez être sûr qu'il se trouve dans votre fonction de requête et s'il s'agit en fait d'un goulot d'étranglement,data.table
vous vous êtes gagné la joie de déposer un rapport. Cela est également vrai lorsque vous l'dplyr
utilisezdata.table
comme back-end; vous pouvez voir des frais générauxdplyr
mais il y a de fortes chances que ce soit votre requête.En cas de
dplyr
problèmes de performances avec les back-ends, vous pouvez les contourner en enregistrant une fonction pour une évaluation hybride ou (dans le cas des bases de données) en manipulant la requête générée avant l'exécution.Voir également la réponse acceptée à quand est-ce que plyr est meilleur que data.table?
la source