Panoramica
Conosco relativamente data.table
poco, non tanto dplyr
. Ho letto alcune dplyr
vignette ed esempi che sono emersi su SO, e finora le mie conclusioni sono che:
data.table
edplyr
sono comparabili in termini di velocità, tranne quando ci sono molti gruppi (cioè> 10-100 K) e in alcune altre circostanze (vedere i benchmark di seguito)dplyr
ha una sintassi più accessibiledplyr
estrae (o volontà) potenziali interazioni DB- Vi sono alcune differenze di funzionalità minori (vedere "Esempi / Utilizzo" di seguito)
Nella mia mente 2. non ha molto peso perché ne ho abbastanza familiarità data.table
, anche se capisco che per gli utenti nuovi ad entrambi sarà un grande fattore. Vorrei evitare una discussione su quale sia più intuitiva, in quanto irrilevante per la mia domanda specifica posta dal punto di vista di qualcuno che ha già familiarità data.table
. Vorrei anche evitare una discussione su come "più intuitivo" porta ad un'analisi più rapida (sicuramente vero, ma di nuovo, non di ciò che mi interessa di più qui).
Domanda
Quello che voglio sapere è:
- Ci sono compiti analitici che sono molto più facili da codificare con l'uno o l'altro pacchetto per le persone che hanno familiarità con i pacchetti (cioè una combinazione di sequenze di tasti richieste rispetto al livello richiesto di esoterismo, dove meno di ciascuna è una buona cosa).
- Esistono attività analitiche che vengono eseguite sostanzialmente (cioè più di 2 volte) in modo più efficiente in un pacchetto rispetto a un altro.
Una recente domanda SO mi ha fatto riflettere un po 'di più su questo, perché fino a quel momento non pensavo che dplyr
avrebbe offerto molto al di là di quello che già posso fare data.table
. Ecco la dplyr
soluzione (dati alla fine di Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Che era molto meglio del mio tentativo di hacking di una data.table
soluzione. Detto questo, anche le buone data.table
soluzioni sono abbastanza buone (grazie Jean-Robert, Arun, e nota che ho preferito una singola affermazione rispetto alla soluzione strettamente ottimale):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
La sintassi per quest'ultima può sembrare molto esoterica, ma in realtà è piuttosto semplice se sei abituato data.table
(cioè non usa alcuni dei trucchi più esoterici).
Idealmente quello che mi piacerebbe vedere sono alcuni buoni esempi in cui il modo dplyr
o data.table
è sostanzialmente più conciso o offre prestazioni sostanzialmente migliori.
Esempi
usodplyr
non consente operazioni raggruppate che restituiscono un numero arbitrario di righe (dalla domanda di eddi , nota: sembra che sarà implementato in dplyr 0.5 , inoltre, @beginneR mostra un potenziale rimedio usandodo
nella risposta alla domanda di @ eddi).data.table
supporta i join a rotazione (grazie a @dholstius) nonché i join a sovrapposizionedata.table
ottimizza internamente le espressioni del moduloDT[col == value]
oDT[col %in% values]
per la velocità attraverso l'indicizzazione automatica che utilizza la ricerca binaria utilizzando la stessa sintassi R di base. Vedi qui per maggiori dettagli e un piccolo benchmark.dplyr
offre versioni di valutazione standard di funzioni (ad esregroup
.summarize_each_
) che possono semplificare l'uso programmatico didplyr
(notare che l'uso programmatico didata.table
è sicuramente possibile, richiede solo un po 'di attenta riflessione, sostituzione / quotazione, ecc., almeno per quanto ne so)
- Ho eseguito i miei parametri di riferimento e ho scoperto che entrambi i pacchetti sono comparabili nell'analisi di stile "split Apply Combine", tranne quando ci sono un numero molto elevato di gruppi (> 100 K) a quel punto
data.table
diventa sostanzialmente più veloce. - @Arun ha eseguito alcuni benchmark sui join , dimostrando che la
data.table
scala è migliore rispettodplyr
all'aumento del numero di gruppi (aggiornato con recenti miglioramenti in entrambi i pacchetti e versione recente di R). Inoltre, un punto di riferimento quando si cerca di ottenere valori univoci hadata.table
~ 6 volte più veloce. - (Non verificato) ha il
data.table
75% più veloce su versioni più grandi di un gruppo / applica / ordina mentredplyr
era del 40% più veloce su quelle più piccole ( un'altra domanda SO dai commenti , grazie Danas). - Matt, il principale autore di
data.table
, ha benchmark operazioni raggruppamento sudata.table
,dplyr
e pitonepandas
su un massimo di 2 miliardi di righe (~ 100GB di RAM) . - Un benchmark precedente su gruppi da 80.000 ha
data.table
circa 8 volte più veloce
Dati
Questo è per il primo esempio che ho mostrato nella sezione delle domande.
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
e i data.table
team stanno lavorando su parametri di riferimento, quindi una risposta ci sarà ad un certo punto. # 2 (sintassi) imO è rigorosamente falso, ma questo si avventura chiaramente nel territorio dell'opinione pubblica, quindi voterò anche per chiudere.
(d)plyr
ha la misura 0
dplyr
e plyr
per quanto riguarda la sintassi ed è fondamentalmente il motivo principale per cui non mi piace la loro sintassi, è che devo imparare troppe (leggi più di 1) funzioni extra (con nomi che ancora non ha senso per me), ricorda cosa fanno, quali argomenti prendono, ecc. È sempre stata una grande svolta per me dalla filosofia plyr.
.SD
.). [seriamente] Penso che queste siano differenze di design legittime che si rivolgono a persone diverse
dplyr
quella è:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]