Visión general
Estoy relativamente familiarizado data.table
, no tanto dplyr
. He leído algunas dplyr
viñetas y ejemplos que han aparecido en SO, y hasta ahora mis conclusiones son que:
data.table
ydplyr
son comparables en velocidad, excepto cuando hay muchos (es decir,> 10-100K) grupos, y en algunas otras circunstancias (ver puntos de referencia a continuación)dplyr
tiene una sintaxis más accesibledplyr
abstrae (o lo hará) posibles interacciones de DB- Existen algunas diferencias menores de funcionalidad (consulte "Ejemplos / Uso" a continuación)
En mi opinión 2. no tiene mucho peso porque estoy bastante familiarizado con él data.table
, aunque entiendo que para los usuarios nuevos en ambos será un gran factor. Me gustaría evitar una discusión sobre cuál es más intuitiva, ya que es irrelevante para mi pregunta específica formulada desde la perspectiva de alguien que ya está familiarizado data.table
. También me gustaría evitar una discusión sobre cómo "más intuitivo" conduce a un análisis más rápido (ciertamente cierto, pero de nuevo, no es lo que más me interesa aquí).
Pregunta
Lo que quiero saber es:
- ¿Existen tareas analíticas que sean mucho más fáciles de codificar con uno u otro paquete para personas familiarizadas con los paquetes (es decir, alguna combinación de pulsaciones de teclas requeridas versus nivel requerido de esoterismo, donde menos de cada una es una buena cosa).
- ¿Existen tareas analíticas que se realizan sustancialmente (es decir, más de 2 veces) de manera más eficiente en un paquete en comparación con otro.
Una pregunta reciente de SO me hizo pensar un poco más sobre esto, porque hasta ese momento no pensé dplyr
que ofrecería mucho más de lo que ya puedo hacer data.table
. Aquí está la dplyr
solución (datos al final de Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Lo cual fue mucho mejor que mi intento de hackear una data.table
solución. Dicho esto, las buenas data.table
soluciones también son bastante buenas (gracias Jean-Robert, Arun, y tenga en cuenta que preferí una sola declaración sobre la solución estrictamente más óptima):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
La sintaxis para este último puede parecer muy esotérica, pero en realidad es bastante sencilla si estás acostumbrado data.table
(es decir, no usa algunos de los trucos más esotéricos).
Lo ideal sería que lo que me gustaría ver es algunos ejemplos de buenas fueron el dplyr
o data.table
forma es sustancialmente más concisa o realiza sustancialmente mejor.
Ejemplos
Usodplyr
no permite operaciones agrupadas que devuelven un número arbitrario de filas (de la pregunta de eddi , nota: parece que se implementará en dplyr 0.5 , también, @beginneR muestra una posible solución alternativado
en la respuesta a la pregunta de @ eddi).data.table
admite uniones continuas (gracias @dholstius) así como uniones superpuestasdata.table
optimiza internamente las expresiones de la formaDT[col == value]
oDT[col %in% values]
de la velocidad a través de la indexación automática que usa la búsqueda binaria mientras usa la misma sintaxis R base. Vea aquí para más detalles y un pequeño punto de referencia.dplyr
ofrece versiones de evaluación estándar de funciones (pregroup
. ej .summarize_each_
) que pueden simplificar el uso programático dedplyr
(tenga en cuenta que el uso programáticodata.table
es definitivamente posible, solo requiere un pensamiento cuidadoso, sustitución / cita, etc., al menos que yo sepa)
- Ejecuté mis propios puntos de referencia y encontré que ambos paquetes son comparables en el análisis de estilo "dividir, aplicar, combinar", excepto cuando hay un gran número de grupos (> 100K) en cuyo punto se
data.table
vuelve sustancialmente más rápido. - @Arun ejecutó algunos puntos de referencia en las uniones , lo que demuestra que se
data.table
escala mejor que adplyr
medida que aumenta el número de grupos (actualizado con mejoras recientes tanto en paquetes como en versiones recientes de R). Además, un punto de referencia al intentar obtener valores únicos tienedata.table
~ 6 veces más rápido. - (Sin verificar) tiene un
data.table
75% más rápido en las versiones más grandes de un grupo / aplicar / ordenar, mientras quedplyr
fue un 40% más rápido en las más pequeñas ( otra pregunta SO de los comentarios , gracias danas). - Matt, el autor principal del
data.table
, ha referenciado operaciones de agrupamiento endata.table
,dplyr
y Pythonpandas
en un máximo de 2 mil millones de filas (~ 100 GB en RAM) . - Un punto de referencia anterior en grupos de 80K tiene
data.table
~ 8 veces más rápido
Datos
Este es el primer ejemplo que mostré en la sección de preguntas.
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
y los data.table
equipos están trabajando en puntos de referencia, por lo que habrá una respuesta en algún momento. # 2 (sintaxis) imO es estrictamente falso, pero eso claramente se aventura en territorio de opinión, por lo que también votaré para cerrar.
(d)plyr
tiene la medida 0
dplyr
y plyr
con respecto a la sintaxis y es básicamente la razón principal por la que no me gusta su sintaxis, es que tengo que aprender demasiadas (leer más de 1) funciones adicionales (con nombres que todavía no tiene sentido para mí), recuerda lo que hacen, los argumentos que toman, etc. Eso siempre ha sido un gran desvío para mí de la filosofía plyr.
.SD
. ej .). [en serio] Creo que estas son diferencias de diseño legítimas que
dplyr
es:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]