[R] substitute in a named expression

Gabor Grothendieck ggrothendieck at gmail.com
Thu Jun 23 00:47:07 CEST 2005


On 6/22/05, Søren Højsgaard <Soren.Hojsgaard at agrsci.dk> wrote:
> I have a 'named expression' like
>  expr <- expression(rep(1,d))
> and would like to replace the argument d with say 5 without actually evaluating the expression. So I try  substitute(expr, list(d=5)) in which case R simply returns expr which when I 'evaluate' it gives
>  eval(expr)
>  Error in rep.default(1, d) : invalid number of copies in rep()
> 
> I've looked at ?substitute and ?expression (and other places) for ideas, but - well I guess there are some details which I haven't quite understood. Can anyone point me in the right direction?

Try this:

eval(substitute(substitute(qq, list(d=5)), list(qq = expr[[1]])))

This aspect of R drove me crazy some time ago but Tony Plate finally figured 
it out and discussed it some time back:
   http://tolstoy.newcastle.edu.au/R/help/04/03/1247.html
There is also a handy utility routine, esub, defined there.

The key points are:

- substitute won't go inside expressions but it will go inside call objects.
  In this case your expr is an expression but expr[[1]] is a call object with
  the desired contents.  Note that quote will return a call
  object so you can avoid the [[1]] if you define expr as cl <- quote(rep(1,d))
  i.e.  
   cl <- quote(rep(1,d))
   eval(substitute(substitute(cl, list(d=5)), list(cl = cl)))

- substitute autoquotes anything inside it so one must substitute in 
  the first argument to the inner substitute using a second outer substitute.  
  That is, the outer substitute substitutes expr[[1]] (which is evaluated) into 
  the first argument of the inner substitute.

- the outer substitute wraps the result of the inner one in a call so we must 
  perform an eval to get what is within the call.  This part is explained in
  ?substitute

Sorry if this is complicated but that seems to be how it works.  Using
the esub function defined in the link above you can simplify it substantially
like this:

esub(cl, list(d=5))

# or

esub(expr[[1]], list(d=5))




More information about the R-help mailing list