R: Понимание стандартной оценки в mutate_

Я пытаюсь смешивать константы и имена цитируемых переменных, как это предлагается в нестандартной виньетизации, используя 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)

Обратите внимание, что я присвоил результат ленивой оценки символьному вектору ("(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

При вызове любой функции 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= функции 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)

Это потому, что все они эквивалентны

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"))