了解何时在函数中使用 ensym、sym 与 enquo
Understanding when to use ensym, sym vs enquo in a function
我正在努力思考不同的 quo/unquo 语法以及何时应该使用它们。
我主要编写函数来传递数据框和列以用作参数——使用 ggplot 或 summarize/manipulate 数据和 dplyr 进行绘图(group_by、总结、变异等)。然而,有时我也不得不使用一个在我的整体功能中不使用 NSE 的功能。
根据我的阅读,我的理解是:
1) 如果我引用数据框中的列,那么我不需要捕获环境,我可以使用 ensym
或 sym
。 这是正确的吗?使用 enquo
会不会有问题,或者只是没有必要?
2) 如果我使用 ensym
,用户可以在技术上在参数中输入字符串或裸列名称。
基于此,我的典型函数设置如下所示:
library(tidyverse)
dataset <- mtcars
myfun <- function(dat, xvar, yvar, group){
#either manipulate data
x <- dat %>% group_by(!!ensym(group)) %>%
mutate(new = !!ensym(xvar)*5) %>%
summarize(medianx=median(!!ensym(xvar), na.rm=TRUE),
median_new=median(new, na.rm=TRUE))
#or plot data
p <- ggplot(dat, aes(x=!!ensym(xvar), y=!!ensym(yvar))) +
geom_point()
#sometime require referencing the column with NSE function..
median(dat[[xvar]]) #works if require string in argument
#how would you reference this with bare argument column? Convert ensym to string?
median(dat[[?????]])
}
#both work with ensym, only the later with sym
myfun(dataset, xvar=mpg, yvar=disp, group=cyl)
myfun(dataset, xvar="mpg", yvar="disp", group="cyl")
如何将裸列参数或符号转换为字符串以供上面 myfun 的最后一行使用? 我尝试了 rlang::as_string(!!ensym(xvar))
但它没有工作。
您的理解是正确的。引用现有数据框中的列时,首选 sym
/ensym
。 enquo()
当然也可以工作,但它捕获任意表达式,允许用户指定诸如 mpg * cyl
或 log10(mpg + cyl)/2
之类的内容。如果您的下游代码假定 xvar
和 yvar
是单列,则具有任意表达式可能会导致问题或意外行为。从这个意义上讲,当您希望引用单个列时,ensym()
会执行参数验证步骤。
至于将符号转换为字符串,一种方法是使用 deparse()
:
median(dat[[deparse(ensym(xvar))]])
要使 rlang::as_string
起作用,您需要删除 !!
,因为您要将表达式本身转换为字符串,而不是表达式所指的内容(例如,mpg
, cyl
, 等等):
median(dat[[rlang::as_string(ensym(xvar))]])
我正在努力思考不同的 quo/unquo 语法以及何时应该使用它们。
我主要编写函数来传递数据框和列以用作参数——使用 ggplot 或 summarize/manipulate 数据和 dplyr 进行绘图(group_by、总结、变异等)。然而,有时我也不得不使用一个在我的整体功能中不使用 NSE 的功能。
根据我的阅读,我的理解是:
1) 如果我引用数据框中的列,那么我不需要捕获环境,我可以使用 ensym
或 sym
。 这是正确的吗?使用 enquo
会不会有问题,或者只是没有必要?
2) 如果我使用 ensym
,用户可以在技术上在参数中输入字符串或裸列名称。
基于此,我的典型函数设置如下所示:
library(tidyverse)
dataset <- mtcars
myfun <- function(dat, xvar, yvar, group){
#either manipulate data
x <- dat %>% group_by(!!ensym(group)) %>%
mutate(new = !!ensym(xvar)*5) %>%
summarize(medianx=median(!!ensym(xvar), na.rm=TRUE),
median_new=median(new, na.rm=TRUE))
#or plot data
p <- ggplot(dat, aes(x=!!ensym(xvar), y=!!ensym(yvar))) +
geom_point()
#sometime require referencing the column with NSE function..
median(dat[[xvar]]) #works if require string in argument
#how would you reference this with bare argument column? Convert ensym to string?
median(dat[[?????]])
}
#both work with ensym, only the later with sym
myfun(dataset, xvar=mpg, yvar=disp, group=cyl)
myfun(dataset, xvar="mpg", yvar="disp", group="cyl")
如何将裸列参数或符号转换为字符串以供上面 myfun 的最后一行使用? 我尝试了 rlang::as_string(!!ensym(xvar))
但它没有工作。
您的理解是正确的。引用现有数据框中的列时,首选 sym
/ensym
。 enquo()
当然也可以工作,但它捕获任意表达式,允许用户指定诸如 mpg * cyl
或 log10(mpg + cyl)/2
之类的内容。如果您的下游代码假定 xvar
和 yvar
是单列,则具有任意表达式可能会导致问题或意外行为。从这个意义上讲,当您希望引用单个列时,ensym()
会执行参数验证步骤。
至于将符号转换为字符串,一种方法是使用 deparse()
:
median(dat[[deparse(ensym(xvar))]])
要使 rlang::as_string
起作用,您需要删除 !!
,因为您要将表达式本身转换为字符串,而不是表达式所指的内容(例如,mpg
, cyl
, 等等):
median(dat[[rlang::as_string(ensym(xvar))]])