2016-03-17 61 views
6

我使用動態變量名稱調用mutate。這主要是工作的一個例子是:爲什麼使用list()危險.dots = setNames()在dplyr中使用?

df <- data.frame(a = 1:5, b = 1:5) 
func <- function(a,b){ 
    return(a+b) 
} 
var1 = 'a' 
var2 = 'b' 
expr <- interp(~func(x, y), x = as.name(var1), y = as.name(var2)) 
new_name <- "dynamically_created_name" 
temp <- df %>% mutate_(.dots = setNames(expr, nm = new_name)) 

將會產生

temp 
    a b func(a, b) 
1 1 1   2 
2 2 2   4 
3 3 3   6 
4 4 4   8 
5 5 5   10 

這主要是罰款,除了集名稱忽略了納米關鍵。這是通過列表()包裝我的函數求解:

temp <- df %>% mutate_(.dots = setNames(list(expr), nm = new_name)) 
temp 
    a b dynamically_created_name 
1 1 1      2 
2 2 2      4 
3 3 3      6 
4 4 4      8 
5 5 5      10 

我的問題是爲什麼setNames忽略它擺在首位的關鍵,以及如何列表()解決這一問題?

回答

2

vignettes("nse")

如果你也想輸出變量發生變化,則需要引用對象的列表傳遞給.dots參數

因此,或許原因

temp <- df %>% mutate_(.dots = setNames(expr, nm = new_name)) 

不做你想做的是,雖然你成功地在這裏設置了name屬性,但是expr是sti LL的公式,而不是一個列表:

foo <- setNames(expr, nm = new_name) 
names(foo) #"dynamically_created_name" "" 
class(foo) #"formula" 

所以,如果你把它的列表,它按預期工作:

expr <- interp(~func(x, y), x = as.name(var1), 
       y = as.name(var2)) 
df %>% mutate_(.dots = list(new_name = expr)) 
    a b new_name 
1 1 1  2 
2 2 2  4 
3 3 3  6 
4 4 4  8 
5 5 5  10 
+0

等待那不是它!用'new_name'代替列名,但我們想用它的*值*代替它! – AndrewMacDonald

+0

這實際上引發了一些額外的問題。我認爲我的問題的核心是我不完全理解.dots的語法或功能。是否有文檔或小插圖在「nse」小插圖之外更詳細地處理它? –

+1

有'vignette(「lazyeval」)'也 – AndrewMacDonald

7

正如other answer指出的那樣,.dots參數被假定爲列表和setNames是重命名列表中元素的便捷方式。

.dots參數在做什麼?我們先來看看實際點...的說法。這是一系列要評估的表達式。點...下面是兩個名爲c = ~ a * scale1d = ~ a * scale2的表達式。

scale1 <- -1 
scale2 <- -2 

df %>% 
    mutate_(c = ~ a * scale1, d = ~ a * scale2) 
#> a b c d 
#> 1 1 1 -1 -2 
#> 2 2 2 -2 -4 
#> 3 3 3 -3 -6 
#> 4 4 4 -4 -8 
#> 5 5 5 -5 -10 

我們可以將這些表達式事先捆綁在一個列表中。這就是.dots進來的地方。該參數讓我們告訴mutate_評估列表中的表達式。

bundled <- list(
    c2 = ~ a * scale1, 
    d2 = ~ a * scale2 
) 

df %>% 
    mutate_(.dots = bundled) 
#> a b c2 d2 
#> 1 1 1 -1 -2 
#> 2 2 2 -2 -4 
#> 3 3 3 -3 -6 
#> 4 4 4 -4 -8 
#> 5 5 5 -5 -10 

如果我們想以編程方式更新列表中的表達式的名稱,然後setNames是做到這一點的簡便方法。如果我們希望在編寫表達式時以編程方式混合和匹配常量和變量名稱,那麼lazyeval包提供了方便的方法。下面我做兩個表達式列表,命名它們,並用mutate_來評估它們

# Imagine some dropdown boxes in a Shiny app, and this is what user requested 
selected_func1 <- "min" 
selected_func2 <- "max" 
selected_var1 <- "a" 
selected_var2 <- "b" 

# Assemble expressions from those choices 
bundled2 <- list(
    interp(~fun(x), fun = as.name(selected_func1), x = as.name(selected_var1)), 
    interp(~fun(x), fun = as.name(selected_func2), x = as.name(selected_var2)) 
) 
bundled2 
#> [[1]] 
#> ~min(a) 
#> 
#> [[2]] 
#> ~max(b) 

# Create variable names 
exp_name1 <- paste0(selected_func1, "_", selected_var1) 
exp_name2 <- paste0(selected_func2, "_", selected_var2) 

bundled2 <- setNames(bundled2, c(exp_name1, exp_name2)) 
bundled2 
#> $min_a 
#> ~min(a) 
#> 
#> $max_b 
#> ~max(b) 

# Evaluate the expressions 
df %>% 
    mutate_(.dots = bundled2) 
#> a b min_a max_b 
#> 1 1 1  1  5 
#> 2 2 2  1  5 
#> 3 3 3  1  5 
#> 4 4 4  1  5 
#> 5 5 5  1  5 
+0

謝謝!這正是我需要圍繞什麼點和seNames所做的教程。 –

相關問題