[R] (With trepidation): Evaluating expressions with sub expressions again

Bert Gunter gunter.berton at gene.com
Sun Jan 31 21:00:28 CET 2010


(For R language geeks only)

Folks:

I think the best solution for the issue in the Subject line(see 29 January
thread on this for details) was the one Jennifer and Gabor previously
arrived at: (essentially)don't use R; instead, use a computer algebra system
that you can access through an R interface (e.g. Ryacas).

HOWEVER, I still wondered whether one could come up with a "simple" pure R
solution for simple but more general cases. What I offered previously was
too simple for the general case, as Gabor pointed out. It could do:

substitute the expression, "1/t" for "b" in the expression a*b;

but it could not descend further to handle:

substitute the expression, "1/t" for "b" in the expression a*b, where the
expression "sin(z+3)" is in turn to be substituted for t.

So I fooled with this a bit further and **think** (with trepidation) I found
that my previous approach does seem to extend to the general case by just
repeatedly processing the expression until done. One can even do this
without recursion (as it's tail recursion only) as follows (but see the
caveat below):

esub <- function(expr,sublist)
{
   nm <- names(sublist)
   while(length(intersect(all.vars(expr),nm))){
      sub<- lapply(sublist, function(x)if(is.expression(x))x[[1]] else x)
      expr
<-as.expression(lapply(expr,function(x)do.call(substitute,list(x,sub))))
   }
   expr
}

It can be used as:

Example 1:

> z <- expression(a+b)

> a <- quote(1/t)

> b <- expression(x^2)

> esub(z,list(a=a,b=b))
expression(1/t + x^2)

CAVEAT: Note that all the expressions to be substituted can be formed by
either quote() or expression(), ** but they must be explicitly given in a
list.** In particular, they will not automatically be looked up for in the
frame of the call, as was the case with Gabor's/Tony Plate's version.

Example 2:

> esub(z,list(a=a,b=b, x = quote(t+3), t = quote(exp(y)) ))
expression(1/exp(y) + (exp(y) + 3)^2)

## So now the substitutions properly extend into subexpressions.


Example 3:
## Of course, this also works:
> d <- quote(exp(y))

> esub(z,list(a=a,b=b, x = quote(t^2+3), t = d ))
expression(1/exp(y) + (exp(y)^2 + 3)^2)

I would appreciate being told (on list) if/how this scheme can be broken or
a reference to other approaches (besides that which Gabor provided, of
course). Clever improvements are also always welcome.

Cheers to all,

Bert Gunter
Genentech Nonclinical Statistics



More information about the R-help mailing list