R:理解mutate_中的标准评估

时间:2016-05-16 17:18:04

标签: r dplyr lazy-evaluation

我正在尝试使用lazyeval::interp按照Non-standard evaluation vignette中的建议混合常量和引用的变量名称。

这是一个做我想要的例子:

# create sample dataset
df_foo = data_frame(
  `(Weird) Variable name` = 100,
  group_var = sample(c("Yes", "No"), size = 100, replace = TRUE)
)

# function to update the value of weirdly named variable
update_var_1 = function(var_name) {
  df_foo %>% 
    mutate_(
      "(Weird) Variable name" = 
        interp(quote(ifelse(group_var_val == "Yes", var_name_val/10, var_name_val/20)), 
               group_var_val = as.name("group_var"),
               var_name_val = as.name(var_name))
    )
}

# test the function
update_var_1("(Weird) Variable name") %>% 
  head(n = 20)

请注意,我已将延迟评估的结果分配给字符向量("(Weird) Variable name")。但是,当我将延迟评估的结果分配给var_name并将其分配给名为"var_name"的文字时。有人可以帮助理解这种行为吗?

# function to update the value of weirdly named variable
update_var_2 = function(var_name) {
  df_foo %>% 
    mutate_(
      var_name = 
        interp(quote(ifelse(group_var_val == "Yes", var_name_val/10, var_name_val/20)), 
               group_var_val = as.name("group_var"),
               var_name_val = as.name(var_name))
    )
}

# test the function
update_var_2("(Weird) Variable name") %>% 
  head(n = 20)

两个功能是否应该没有相同的结果?

1 个答案:

答案 0 :(得分:20)

直接调用任何R函数时,不能将变量用于参数名称(并且参数名称是指函数调用中=符号左侧的那些内容)。参数名称始终作为文字值。这两个是相同的

f(a=3)
f("a"=3)

或者看看

deparse(quote(f(a=3)))
# [1] "f(a = 3)"
deparse(quote(f("a"=3)))
# [1] "f(a = 3)"
a <- "b"
deparse(quote(f(a=3)))
# [1] "f(a = 3)"

a不必是第一个工作的变量,即使存在这样的变量,它也会被忽略。解析时基本上抛出了引号 - 它实际上不是字符值,而是符号。

如果需要动态设置变量名,则需要将参数构建为列表并设置该列表的名称。

如果要将参数名称作为字符值传递,可以使用setNames设置参数名称,然后将其传递给.dots=的{​​{1}}参数功能。例如

mutate_

这是因为这些都是等价的

update_var_3 <- function(var_name) {
  df_foo %>% 
    mutate_(.dots=
    setNames(list(
        interp(quote(ifelse(group_var_val == "Yes", var_name_val/10, var_name_val/20)), 
               group_var_val = as.name("group_var"),
               var_name_val = as.name(var_name)
    )), var_name))
}

update_var_3("(Weird) Variable name") %>% 
  head(n = 20)