使用 dplyr 的动词时,非标准评估非常方便。但是在使用带有函数参数的动词时可能会出现问题。例如,假设我想创建一个函数,为我提供给定物种的行数。
# Load packages and prepare data
library(dplyr)
library(lazyeval)
# I prefer lowercase column names
names(iris) <- tolower(names(iris))
# Number of rows for all species
nrow(iris)
# [1] 150
示例不起作用
此函数无法按预期工作,因为species
它是在 iris 数据帧的上下文中解释的,而不是在函数参数的上下文中解释的:
nrowspecies0 <- function(dtf, species){
dtf %>%
filter(species == species) %>%
nrow()
}
nrowspecies0(iris, species = "versicolor")
# [1] 150
3 实施实例
为了解决非标准评估,我通常在参数后面加上下划线:
nrowspecies1 <- function(dtf, species_){
dtf %>%
filter(species == species_) %>%
nrow()
}
nrowspecies1(iris, species_ = "versicolor")
# [1] 50
# Because of function name completion the argument
# species works too
nrowspecies1(iris, species = "versicolor")
# [1] 50
它并不完全令人满意,因为它将函数参数的名称更改为不太用户友好的名称。或者它依赖于自动完成,我担心这不是编程的好习惯。为了保持一个好的参数名称,我可以这样做:
nrowspecies2 <- function(dtf, species){
species_ <- species
dtf %>%
filter(species == species_) %>%
nrow()
}
nrowspecies2(iris, species = "versicolor")
# [1] 50
另一种解决基于此答案的非标准评估的方法。
在函数环境的上下文中interp()
解释:species
nrowspecies3 <- function(dtf, species){
dtf %>%
filter_(interp(~species == with_species,
with_species = species)) %>%
nrow()
}
nrowspecies3(iris, species = "versicolor")
# [1] 50
考虑到上面的 3 个功能,实现此过滤器功能的首选 - 最强大 - 方法是什么?还有其他方法吗?