R:理解mutate_中的标准评估

tch*_*rty 13 r lazy-evaluation dplyr

我试图混合常量和引用变量名,如建议非标准评价暗角使用lazyeval::interp.

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

# 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)
Run Code Online (Sandbox Code Playgroud)

请注意,我已将延迟评估的结果分配给字符向量("(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)
Run Code Online (Sandbox Code Playgroud)

这两个函数应该没有相同的结果吗?

MrF*_*ick 20

当直接调用任何R函数时,不能将变量用于参数名称(并且通过参数名称,我指的是=函数调用中符号左侧的那些东西).参数名称始终作为文字值.这两个是一样的

f(a=3)
f("a"=3)
Run Code Online (Sandbox Code Playgroud)

或者看看

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)"
Run Code Online (Sandbox Code Playgroud)

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

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

如果要将参数名称作为字符值传递,可以使用setNames该参数名称设置可以传递给函数.dots=参数的参数名称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)
Run Code Online (Sandbox Code Playgroud)

这是因为这些都是等价的

df <- data_frame(a=1:10)
mutate(df, a=a+5)
mutate(df, "a"=a+5)  #identical to first, not really a character variable
mutate_(df, a=quote(a+5))
mutate_(df, .dots=list(a=quote(a+5)))
mutate_(df, .dots=setNames(list(quote(a+5)),"a"))
Run Code Online (Sandbox Code Playgroud)