测试使用enquo()作为NULL参数的函数

Sto*_*ker 2 r dplyr

我有一个创建数据框的函数,但是会在过程中更改名称。我正在尝试使用dplyr quosures处理空列名称。我的测试套件如下所示:

dataframe <- data_frame(
  a = 1:5,
  b = 6:10
)

my_fun <- function(df, col_name, new_var_name = NULL) {
  target <- enquo(col_name)

  c <- df %>% pull(!!target) * 3 # here may be more complex calculations

  # handling NULL name
  if (is.null(new_var_name)) {
    new_name <- quo(default_name)
  } else{
    new_name <- enquo(new_name)
  }

  data_frame(
    abc = df %>% pull(!!target),
    !!quo_name(new_name) := c
  )
}
Run Code Online (Sandbox Code Playgroud)

如果我这样调用函数:

my_fun(dataframe, a)
Run Code Online (Sandbox Code Playgroud)

我得到预期的默认名称:

# A tibble: 5 x 2
    abc default_name
  <int>        <dbl>
1     1            3
2     2            6
3     3            9
4     4           12
5     5           15
Run Code Online (Sandbox Code Playgroud)

而且,如果我尝试传递名称,则会收到错误消息:

my_fun(dataframe, a, NEW_NAME)
Error in my_fun(dataframe, a, NEW_NAME) : object 'NEW_NAME' not found
Run Code Online (Sandbox Code Playgroud)

我哪里错了?

MrF*_*ick 7

这个问题其实没有做quoenquo返回不同的东西,它的的确确是评估对象之前,你真的想。如果使用browser()逐步浏览函数,则会在if (is.null(new_var_name))语句中看到错误发生。

当您这样做时is.null(new_var_name),您正在评估按原样传递的变量,new_var_name因此为时已晚enquo。这是因为is.null需要查看变量的值,而不仅仅是变量名本身。

该函数不评估传递给该函数的参数,但会检查该参数是否存在missing()

my_fun <- function(df, col_name, new_var_name=NULL) {
  target <- enquo(col_name)

  c <- df %>% pull(!!target) * 3 # here may be more complex calculations

  # handling NULL name
  if (missing(new_var_name)) {
    new_name <- "default_name"
  } else{
    new_name <- quo_name(enquo(new_var_name))
  }

  data_frame(
    abc = df %>% pull(!!target),
    !!new_name := c
  )
}
Run Code Online (Sandbox Code Playgroud)

然后您可以运行这两个

my_fun(dataframe, a)
my_fun(dataframe, a, NEW_NAME)
Run Code Online (Sandbox Code Playgroud)