-2

I would like to replace the LHS of "=" in a expression in R. In my personal case, I need it to make sure the following creates a variable that does not already exist in the data frame

df %>% mutate(v = mean(w))

I tried eval(substitute()) but the LHS is not substituted

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

Why can't v substituted throught eval/substitute? What's the best way to work around it?

Matthew
  • 2,628
  • 1
  • 20
  • 35
  • 3
    What on earth are you trying to do here. Please read [how to ask a good question](http://stackoverflow.com/help/how-to-ask). introduce the problem for jumping into code. Surely there are better ways to do what you want other than `eval` and `substitute`. Is `pryr` essential here? – MrFlick Sep 20 '14 at 03:03
  • Why not change the name after you perform the operation? – Matthew Lundberg Sep 20 '14 at 03:16
  • Yes indeed I could. But I'm trying to understand whether it's indeed the best way, why the eval(subs()) technique does not work and whether there are other cases than the lhs of a `=` – Matthew Sep 20 '14 at 03:19

1 Answers1

3

1) eval/parse Create a cmd string, parse it and evaluate it:

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

giving

  v1 v1_mean
1  1       2
2  2       2
3  3       2
... etc ...

2) eval/as.call Another way is to construct a list, convert it to a call and evaluate it. (This is also the approach that mutate_each_q in dplyr takes.)

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 We form a list equal to the last two components of the list in the prior solution and then use 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 Added additional solutions.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341