2016-05-16 56 views
12

我試圖混合常量和引用變量名,如使用lazyeval::interpNon-standard evaluation vignette建議瞭解標準的評價。R:在mutate_

下面是一個例子,做什麼,我想:

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

這兩個函數應該沒有相同的結果嗎?

回答

18

當直接調用任何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來設置參數名稱,然後您可以將該參數傳遞給mutate_函數的.dots=參數。例如

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