我使用动态变量名称调用mutate。一个主要有效的例子是:
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
除了集合名称忽略了nm键之外,这很好。这可以通过将我的函数包装在list()中来解决:
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首先忽略它的关键,list()如何解决这个问题?
答案 0 :(得分:10)
如other answer所述,假设.dots参数是一个列表,而setNames是重命名列表中元素的便捷方式。
什么是.dots参数在做什么?让我们首先考虑实际的点...
参数。这是一系列要评估的表达式。点...
下面是两个命名的表达式c = ~ a * scale1
和d = ~ 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
答案 1 :(得分:2)
来自vignettes("nse")
:
如果您还想输出要变化的变量,则需要将引用对象列表传递给
.dots
参数
所以也许是
的原因temp <- df %>% mutate_(.dots = setNames(expr, nm = new_name))
如果您在此处成功设置了name属性,那么expr
仍然是公式,而不是列表:
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