mutate - Diferencia entre subconjunto y filtro de dplyr
funcion mutate en r (5)
De hecho, están produciendo el mismo resultado y son muy similares en concepto.
La ventaja del subset
es que es parte de la base R y no requiere ningún paquete adicional. Con tamaños de muestra pequeños, parece ser un poco más rápido que el filter
(6 veces más rápido en su ejemplo, pero eso se mide en microsegundos).
A medida que los conjuntos de datos crecen, el filter
parece ganar ventaja en eficiencia. Con 15,000 registros, el filter
supera al subset
en unos 300 microsegundos. Y en 153,000 registros, el filter
es tres veces más rápido (medido en milisegundos).
Entonces, en términos de tiempo humano, no creo que haya mucha diferencia entre los dos.
La otra ventaja (y esto es un poco de una ventaja de nicho) es que el filter
puede operar en bases de datos SQL sin llevar los datos a la memoria. subset
simplemente no hace eso.
Personalmente, tiendo a usar el filter
, pero solo porque ya estoy usando el marco dplyr
. Si no está trabajando con datos de memoria insuficiente, no habrá mucha diferencia.
library(dplyr)
library(microbenchmark)
# Original example
microbenchmark(
df1<-subset(airquality, Temp>80 & Month > 5),
df2<-filter(airquality, Temp>80 & Month > 5)
)
Unit: microseconds
expr min lq mean median uq max neval cld
subset 95.598 107.7670 118.5236 119.9370 125.949 167.443 100 a
filter 551.886 564.7885 599.4972 571.5335 594.993 2074.997 100 b
# 15,300 rows
air <- lapply(1:100, function(x) airquality) %>% bind_rows
microbenchmark(
df1<-subset(air, Temp>80 & Month > 5),
df2<-filter(air, Temp>80 & Month > 5)
)
Unit: microseconds
expr min lq mean median uq max neval cld
subset 1187.054 1207.5800 1293.718 1216.671 1257.725 2574.392 100 b
filter 968.586 985.4475 1056.686 1023.862 1036.765 2489.644 100 a
# 153,000 rows
air <- lapply(1:1000, function(x) airquality) %>% bind_rows
microbenchmark(
df1<-subset(air, Temp>80 & Month > 5),
df2<-filter(air, Temp>80 & Month > 5)
)
Unit: milliseconds
expr min lq mean median uq max neval cld
subset 11.841792 13.292618 16.21771 13.521935 13.867083 68.59659 100 b
filter 5.046148 5.169164 10.27829 5.387484 6.738167 65.38937 100 a
Me parece que el subconjunto y el filtro (de dplyr) tienen el mismo resultado. Pero mi pregunta es: ¿hay en algún punto una diferencia potencial, por ejemplo? ¿Velocidad, tamaños de datos que puede manejar, etc.? ¿Hay ocasiones en que es mejor usar uno u otro?
Ejemplo:
library(dplyr)
df1<-subset(airquality, Temp>80 & Month > 5)
df2<-filter(airquality, Temp>80 & Month > 5)
summary(df1$Ozone)
# Min. 1st Qu. Median Mean 3rd Qu. Max. NA''s
# 9.00 39.00 64.00 64.51 84.00 168.00 14
summary(df2$Ozone)
# Min. 1st Qu. Median Mean 3rd Qu. Max. NA''s
# 9.00 39.00 64.00 64.51 84.00 168.00 14
Interesante. Estaba tratando de ver la diferencia en términos del conjunto de datos resultante y no pude obtener una explicación de por qué el operador "[" se comportó de manera diferente (es decir, por qué también devolvió NA):
# Subset for year=2013
sub<-brfss2013 %>% filter(iyear == "2013")
dim(sub)
#[1] 486088 330
length(which(is.na(sub$iyear))==T)
#[1] 0
sub2<-filter(brfss2013, iyear == "2013")
dim(sub2)
#[1] 486088 330
length(which(is.na(sub2$iyear))==T)
#[1] 0
sub3<-brfss2013[brfss2013$iyear=="2013", ]
dim(sub3)
#[1] 486093 330
length(which(is.na(sub3$iyear))==T)
#[1] 5
sub4<-subset(brfss2013, iyear=="2013")
dim(sub4)
#[1] 486088 330
length(which(is.na(sub4$iyear))==T)
#[1] 0
Una diferencia adicional que aún no se menciona es que el filtro descarta los nombres conocidos, mientras que el subconjunto no:
filter(mtcars, gear == 5)
mpg cyl disp hp drat wt qsec vs am gear carb
1 26.0 4 120.3 91 4.43 2.140 16.7 0 1 5 2
2 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2
3 15.8 4 351.0 264 4.22 3.170 14.5 0 1 5 4
4 19.7 4 145.0 175 3.62 2.770 15.5 0 1 5 6
5 15.0 4 301.0 335 3.54 3.570 14.6 0 1 5 8
subset(mtcars, gear == 5)
mpg cyl disp hp drat wt qsec vs am gear carb
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.7 0 1 5 2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.9 1 1 5 2
Ford Pantera L 15.8 4 351.0 264 4.22 3.170 14.5 0 1 5 4
Ferrari Dino 19.7 4 145.0 175 3.62 2.770 15.5 0 1 5 6
Maserati Bora 15.0 4 301.0 335 3.54 3.570 14.6 0 1 5 8
Una diferencia también es que el subconjunto hace más cosas que el filtro, también puede seleccionar y soltar mientras tiene dos funciones diferentes en dplyr
subset(df, select=c("varA", "varD"))
dplyr::select(df,varA, varD)
Una ventaja adicional del filter
es que juega bien con los datos agrupados. subset
ignora las agrupaciones.
Entonces, cuando los datos están agrupados, el subset
seguirá haciendo referencia a todos los datos, pero el filter
solo hará referencia al grupo.
# setup
library(tidyverse)
data.frame(a = 1:2) %>% group_by(a) %>% subset(length(a) == 1)
# returns empty table
data.frame(a = 1:2) %>% group_by(a) %>% filter(length(a) == 1)
# returns all rows