使用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
另一种基于this answer解决非标准评估的方法 . interp()
在函数环境的上下文中解释 species
:
nrowspecies3 <- function(dtf, species){
dtf %>%
filter_(interp(~species == with_species,
with_species = species)) %>%
nrow()
}
nrowspecies3(iris, species = "versicolor")
# [1] 50
考虑到上面的3函数,实现这个过滤函数的首选方法是什么?还有其他方法吗?
3 回答
@eddi 的答案是正确的's going on here. I'正在编写另一个答案,解决了如何使用
dplyr
动词编写函数的更大请求 . 你会注意到,最终,它使用像nrowspecies2
这样的东西来避免species == species
重言式 .要编写一个包含将与NSE一起使用的dplyr动词的函数,请编写两个函数:
First 使用
lazyeval
和dplyr
动词的SE版本编写需要引用输入的版本 . 所以在这种情况下,filter_
.Second 制作使用NSE的版本:
***** =如果你想做一些更复杂的事情,你可能需要在这里使用
lazyeval::interp
,如下面链接的提示****** =另外,如果需要更改输出名称,请参阅
.dots
参数对于上述情况,我跟着some tips from Hadley
另一个好的资源是the dplyr vignette on NSE,它说明了
.dots
,interp
和lazyeval
包中的其他功能关于lazyeval的更多细节see it's vignette
有关使用NSE的基本R工具的详尽讨论(其中许多
lazyeval
可帮助您避免),请参阅高级R中的the chapter on NSE这个问题与非标准评估完全无关 . 让我重写你的初始函数,使其清楚:
filter
中的表达式总是求值为TRUE
(几乎总是 - 见下面的例子),这是因为某些NSE魔法,所以_1872203不起作用 .你的
nrowspecies2
是要走的路 .您的
nrowspecies0
中的Fwiw,species
确实被评估为一列,而不是输入变量species
,您可以通过将nrowspecies0(iris, NA)
与nrowspecies4(iris, NA)
进行比较来检查 .in his 2016 UseR talk(@ 38min30s),Hadley Wickham解释了referential transparency的概念 . 使用公式,过滤函数可以重新表述为:
这具有更通用的额外好处