非标准评估在使用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
在上下文中被解释为鸢尾花数据框的一部分,而不是被解释为函数参数的一部分:
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
考虑以上三个功能,实现此过滤函数的最佳和最强大的方式是什么?还有其他方法吗?