奇怪的 dplyr+NSE:在 mutate 中的自定义函数中使用 NSE
Weird dplyr+NSE: using NSE in custom function inside mutate
我在 dplyr::mutate
内的自定义函数中使用 NSE 时偶然发现了一个问题。考虑以下代码:
require(tidyverse)
f <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
return(substitute(v1 + v2))
}
iris %>%
mutate(
test = f(Sepal) %>% eval()
)
ff <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
substitute(v1 + v2) %>% eval.parent(n = 1)
}
iris %>%
mutate(
test = ff(Sepal)
)
此处 f
工作正常,但需要外部调用 eval()
才能在 mutate()
环境中执行代码。
这当然有点难看并导致大量样板代码。我对这项工作的最佳猜测是 ff
,它试图在其调用环境中评估构造的表达式——我希望它是 mutate()
环境。但是,这会抛出一个变量未找到的错误。
关于如何使这项工作以及根本问题是什么的任何想法?本质上我想在 dplyr 动词中允许自定义 'macros' 。
使用 !!
整洁求值 "unquote" 运算符:
ff <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
substitute(v1 + v2)
}
iris %>%
head() %>%
mutate(
test = !! ff(Sepal)
)
我在 dplyr::mutate
内的自定义函数中使用 NSE 时偶然发现了一个问题。考虑以下代码:
require(tidyverse)
f <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
return(substitute(v1 + v2))
}
iris %>%
mutate(
test = f(Sepal) %>% eval()
)
ff <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
substitute(v1 + v2) %>% eval.parent(n = 1)
}
iris %>%
mutate(
test = ff(Sepal)
)
此处 f
工作正常,但需要外部调用 eval()
才能在 mutate()
环境中执行代码。
这当然有点难看并导致大量样板代码。我对这项工作的最佳猜测是 ff
,它试图在其调用环境中评估构造的表达式——我希望它是 mutate()
环境。但是,这会抛出一个变量未找到的错误。
关于如何使这项工作以及根本问题是什么的任何想法?本质上我想在 dplyr 动词中允许自定义 'macros' 。
使用 !!
整洁求值 "unquote" 运算符:
ff <- function(var) {
varname <- deparse(substitute(var))
v1 <- as.name(sprintf("%s.Width", varname))
v2 <- as.name(sprintf("%s.Length", varname))
substitute(v1 + v2)
}
iris %>%
head() %>%
mutate(
test = !! ff(Sepal)
)