我想替换" ="的LHS。在R中的表达式中。在我个人的情况下,我需要它来确保以下内容创建一个数据框中尚不存在的变量
df %>% mutate(v = mean(w))
我尝试eval(substitute())
但LHS未被替换
eval(substitute(df %>% mutate(v = mean(w)), list(v = as.name("id"))))
#similarly in a list
eval(substitute(l <- list(v=1:10),list(v=as.name("id"))))
l
$v
[1] 1 2 3 4 5 6 7 8 9 10
为什么不能通过评估/替代替换v
?什么是最好的解决方法?
答案 0 :(得分:3)
1)eval / parse 创建一个cmd
字符串,解析并评估它:
f2 <- function(DF, x, env = parent.frame()){
cmd <- sprintf("mutate(%s, %s = mean(v1))", deparse(substitute(DF)), x)
eval(parse(text = cmd), env)
}
f2(DF, "v1_name")
给
v1 v1_mean
1 1 2
2 2 2
3 3 2
... etc ...
2)eval / as.call 另一种方法是构建一个列表,将其转换为一个调用并对其进行评估。 (这也是dplyr中mutate_each_q
采用的方法。)
f3 <- function(DF, x, env = parent.frame()) {
L <- list(quote(mutate), .data = substitute(DF), quote(mean(v1)))
names(L)[3] <- x
eval(as.call(L), env)
}
f3(DF, "v1_name")
3)do.call 我们在先前的解决方案中形成一个等于列表最后两个组件的列表,然后使用do.call
:
f3 <- function(DF, x, env = parent.frame()) {
L <- list(.data = substitute(DF), quote(mean(v1)))
names(L)[2] <- x
do.call(mutate, L)
}
f3(DF, "v1_name")
Upodate 添加了其他解决方案。