在主要的使用情况下,它们的行为是相同的:
library(dplyr)
identical(
filter(starwars, species == "Wookiee"),
subset(starwars, species == "Wookiee"))
但是它们有很多差异,其中包括:
subset
可以用于矩阵
filter
可以用于数据库
filter
删除行名称
subset
除了类、名称和行名称外还会删除其他属性。
subset
有一个 select
参数
subset
会对其条件参数进行循环利用
filter
支持将条件作为单独的参数
filter
保留列的类别
filter
支持 .data
代词
filter
支持某些 rlang
特性
filter
支持分组
filter
支持 n()
和 row_number()
filter
更为严格
filter
在计数时略快一些
subset
在其他包中具有方法
subset
可以用于矩阵
subset(state.x77, state.x77[,"Population"] < 400)
虽然在 subset
参数中不能直接使用列作为变量
subset(state.x77, Population < 400)
在 subset.matrix(state.x77, Population < 400) 中出现错误:未找到对象'Population'
filter
也无法使用。
filter(state.x77, state.x77[,"Population"] < 400)
UseMethod("filter_") 函数出错:对于类为 "c('matrix', 'double', 'numeric')" 的对象,没有适用的 'filter_' 方法。
filter(state.x77, Population < 400)
Error in UseMethod("filter_") : no applicable method for 'filter_'
applied to an object of class "c('matrix', 'double', 'numeric')"
filter
可以用于数据库
library(DBI)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "mtcars", mtcars)
tbl(con,"mtcars") %>%
filter(hp < 65)
subset
无法
tbl(con,"mtcars") %>%
subset(hp < 65)
在 subset.default(., hp < 65) 中出现错误:未找到对象 'hp'
filter
函数会删除行名称
filter(mtcars, hp < 65)
< p >
subset
不起作用。
subset(mtcars, hp < 65)
subset
方法可以丢弃除class、names和row names之外的属性。
cars_head <- head(cars)
attr(cars_head, "info") <- "head of cars dataset"
attributes(subset(cars_head, speed > 0))
attributes(filter(cars_head, speed > 0))
subset
有一个select
参数
dplyr
遵循tidyverse
的原则,每个函数只做一件事情,因此select
是一个单独的函数。
identical(
subset(starwars, species == "Wookiee", select = c("name", "height")),
filter(starwars, species == "Wookiee") %>% select(name, height)
)
它还有一个drop
参数,这个参数在使用select
参数的上下文中才有意义。
subset
会循环使用条件参数。
half_iris <- subset(iris,c(TRUE,FALSE))
dim(iris)
dim(half_iris)
filter
不能做到
half_iris <- filter(iris,c(TRUE,FALSE))
筛选器实现中的错误(.data,quo):结果的长度必须为150而不是2
filter
支持将条件作为单独的参数
将条件提供给...
,因此我们可以将多个条件作为不同的参数,这与使用&
相同,但有时由于逻辑运算符优先级和自动缩进,可能更易读。
identical(
subset(starwars,
(species == "Wookiee" | eye_color == "blue") &
mass > 120),
filter(starwars,
species == "Wookiee" | eye_color == "blue",
mass > 120)
)
filter
保留列的类(class)
df <- data.frame(a=1:2, b = 3:4, c= 5:6)
class(df$a) <- "foo"
class(df$b) <- "Date"
str(subset(df,TRUE))
str(dplyr::filter(df,TRUE))
filter
函数支持使用 .data
代词
mtcars %>% filter(.data[["hp"]] < 65)
filter
支持一些rlang
功能
x <- "hp"
library(rlang)
mtcars %>% filter(!!sym(x) < 65)
filter65 <- function(data,var){
data %>% filter(!!enquo(var) < 65)
}
mtcars %>% filter65(hp)
filter
支持分组
iris %>%
group_by(Species) %>%
filter(Petal.Length < quantile(Petal.Length,0.01))
iris %>%
group_by(Species) %>%
subset(Petal.Length < quantile(Petal.Length,0.01))
filter
支持 n()
和 row_number()
filter(iris, row_number() < n()/30)
filter
更加严格
如果输入不合规,则将触发错误。
filter(iris, Species = "setosa")
identical(subset(iris, Species = "setosa"), iris)
df1 <- setNames(data.frame(a = 1:3, b=5:7),c("a","a"))
filter(df1, a > 2)
subset(df1, a > 2)
filter
在计数时速度更快
借用Benjamin在他的答案中构建的数据集(153 k行),尽管它应该很少成为瓶颈,但速度快了一倍。
air <- lapply(1:1000, function(x) airquality) %>% bind_rows
microbenchmark::microbenchmark(
subset = subset(air, Temp>80 & Month > 5),
filter = filter(air, Temp>80 & Month > 5)
)
subset
在其他包中有方法
subset
是一个S3通用函数,就像dplyr::filter
一样,但是subset
作为基本函数更有可能在其他包中开发方法,一个突出的例子是zoo:::subset.zoo
。
subset
、filter
、with
和[
四种方法,并介绍了在使用 dplyr 子集化数据框时如何使用|
和&
进行逻辑判断。原文链接为:如何使用 | 和 & 在 dplyr 中子集化数据框。 - Silence Dogoodsubset
在?subset
中带有警告:“这是一个旨在交互使用的便利函数。对于编程,最好使用标准的子集函数,如[
,特别是参数子集的非标准评估可能会产生意想不到的后果。”filter
旨在与dplyr和tidyverse的其余部分稳健地交互使用,无论是交互式还是编程式,并且具有单独的标准评估版本filter_
(必要时)。此外,它将逗号视为&
。 - alistairefilter_()
和_
版本通常已被弃用,取而代之的是整洁评估语义。有关当前最佳实践的详细信息,请参阅使用dplyr进行编程。 - Bryan Shalloway