整洁的评估范围是否有限制?
Are there limits to tidy evaluation scope?
我正在尝试使用 dplyr 0.7.0
中定义的整洁求值。
但是,在 mutate()
中的函数调用期间,我遇到了错误。似乎没有像我预期的那样评估变量。
library(dplyr)
library(tibble)
library(tidyr)
myCor <- function(col1, col2) {
col1 <- enquo(col1)
col2 <- enquo(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
myCor("mpg", "disp")
# Error in mutate_impl(.data, dots) :
# Evaluation error: 'x' must be numeric.
相反,我必须使用这种不整洁的 eval 语法来获得所需的输出。
myCor <- function(col1, col2) {
col1_tidy <- enquo(col1)
col2_tidy <- enquo(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1_tidy, !!col2_tidy) %>%
mutate(correlation=cor(eval(parse(text=col1)), eval(parse(text=col2))))
}
myCor("mpg", "disp")
# vehicle mpg disp correlation
# 1 Mazda RX4 21.0 160.0 -0.8475514
# 2 Mazda RX4 Wag 21.0 160.0 -0.8475514
# 3 Datsun 710 22.8 108.0 -0.8475514
# 4 Hornet 4 Drive 21.4 258.0 -0.8475514
# ...
有没有办法在整个示例中使用整洁的评估?
来自小插图 Programming with dplyr:
Most dplyr arguments are not referentially transparent. That means you can’t replace a value with a seemingly equivalent object that you’ve defined elsewhere.
因此您需要将未加引号的列名传递给函数,然后使用 enquo
环境被正确捕获,并且 !!
returns 未加引号的列名作为 mutate
期待它。
要将正常的 mutate
调用转换为具有非标准评估的函数,这样开始可能更直观。
首先像没有函数一样写下调用:
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, mpg, disp) %>%
mutate(correlation = cor(mpg, disp))
这有效(并且会在引用 mpg
和 disp
时引发错误!)。
现在拉变量,你想在调用前改变并替换它们:
col1 <- quo(mpg)
col2 <- quo(disp)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
因为这在函数之外,我们必须在这里使用 quo
,但在最后一步,当我们将它包装在函数中时,我们使用 enquo
。
myCor <- function(var1, var2) {
col1 <- enquo(var1)
col2 <- enquo(var2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
我为函数参数使用了不同的名称,然后是 "quoted" 对象(使用 enquo
)以使区别更清楚,但当然它适用于 col1
和 col2
还有。
如果您想将字符串作为参数传递,请使用 ensym
而不是 enquo
...
library(dplyr)
library(rlang)
library(tibble)
myCor <- function(col1, col2) {
col1 <- ensym(col1)
col2 <- ensym(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
# both of these will work now
myCor("mpg", "disp")
myCor(mpg, disp)
我正在尝试使用 dplyr 0.7.0
中定义的整洁求值。
但是,在 mutate()
中的函数调用期间,我遇到了错误。似乎没有像我预期的那样评估变量。
library(dplyr)
library(tibble)
library(tidyr)
myCor <- function(col1, col2) {
col1 <- enquo(col1)
col2 <- enquo(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
myCor("mpg", "disp")
# Error in mutate_impl(.data, dots) :
# Evaluation error: 'x' must be numeric.
相反,我必须使用这种不整洁的 eval 语法来获得所需的输出。
myCor <- function(col1, col2) {
col1_tidy <- enquo(col1)
col2_tidy <- enquo(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1_tidy, !!col2_tidy) %>%
mutate(correlation=cor(eval(parse(text=col1)), eval(parse(text=col2))))
}
myCor("mpg", "disp")
# vehicle mpg disp correlation
# 1 Mazda RX4 21.0 160.0 -0.8475514
# 2 Mazda RX4 Wag 21.0 160.0 -0.8475514
# 3 Datsun 710 22.8 108.0 -0.8475514
# 4 Hornet 4 Drive 21.4 258.0 -0.8475514
# ...
有没有办法在整个示例中使用整洁的评估?
来自小插图 Programming with dplyr:
Most dplyr arguments are not referentially transparent. That means you can’t replace a value with a seemingly equivalent object that you’ve defined elsewhere.
因此您需要将未加引号的列名传递给函数,然后使用 enquo
环境被正确捕获,并且 !!
returns 未加引号的列名作为 mutate
期待它。
要将正常的 mutate
调用转换为具有非标准评估的函数,这样开始可能更直观。
首先像没有函数一样写下调用:
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, mpg, disp) %>%
mutate(correlation = cor(mpg, disp))
这有效(并且会在引用 mpg
和 disp
时引发错误!)。
现在拉变量,你想在调用前改变并替换它们:
col1 <- quo(mpg)
col2 <- quo(disp)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
因为这在函数之外,我们必须在这里使用 quo
,但在最后一步,当我们将它包装在函数中时,我们使用 enquo
。
myCor <- function(var1, var2) {
col1 <- enquo(var1)
col2 <- enquo(var2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
我为函数参数使用了不同的名称,然后是 "quoted" 对象(使用 enquo
)以使区别更清楚,但当然它适用于 col1
和 col2
还有。
如果您想将字符串作为参数传递,请使用 ensym
而不是 enquo
...
library(dplyr)
library(rlang)
library(tibble)
myCor <- function(col1, col2) {
col1 <- ensym(col1)
col2 <- ensym(col2)
mtcars %>%
rownames_to_column("vehicle") %>%
select(vehicle, !!col1, !!col2) %>%
mutate(correlation=cor(!!col1, !!col2))
}
# both of these will work now
myCor("mpg", "disp")
myCor(mpg, disp)