[R] evaluating expressions with sub expressions

Bert Gunter gunter.berton at gene.com
Fri Jan 29 23:42:01 CET 2010


Inline below...

-----Original Message-----
From: Gabor Grothendieck [mailto:ggrothendieck at gmail.com] 
Sent: Friday, January 29, 2010 2:12 PM
To: Bert Gunter
Cc: Jennifer Young; r-help at r-project.org
Subject: Re: [R] evaluating expressions with sub expressions

If its good enough to have one level of substitution then esub in my
post (originally due to Tony Plate -- see reference in my post) is all
that is needed:

esub(mat[[2]], list(g1 = g1[[1]]))

--- Yes, this is essentially what I did using lapply

but I think the real problem could require multiple levels of
substitution in which case repeated application of esub is needed as
you walk the expression tree which is what proc() in my post does.

-- Indeed. But my point was to handle the simple case simply.


To answer your question, quote() produces a call object but expression
produces a call wrapped in an expression which is why there is special
handling of expression objects in the proc() function in my post.

-- Aha! And of course I should have realized that I could have easily
determined this myself with:

> as.list(quote(a*b))
[[1]]
`*`

[[2]]
a

[[3]]
b

## But ...

> e <- as.list(expression(a*b))
> e
[[1]]
a * b

> mode(e[[1]])
[1] "call"
> as.list(e[[1]])
[[1]]
`*`

[[2]]
a

[[3]]
b

So now all is clear to me.

Thanks to both Bill and Gabor for their informative replies.

-- Bert

Bert Gunter
Genentech Nonclinical Statistics


On Fri, Jan 29, 2010 at 4:38 PM, Bert Gunter <gunter.berton at gene.com> wrote:
> Folks:
>
> Stripped to its essentials, Jennifer's request seemed simple: substitute a
> subexpression as a named variable for a variable name in an expression,
also
> expressed as a named variable. A simple example is:
>
>> e <- expression(0,a*b)
>> z1 <- quote(1/t) ## explained below
>
> The task is to "substitute" the expression in z1, "1/t", for "b" in e,
> yielding the substituted expression as the result.
>
> Gabor provided a solution, but it seemed to me like trying to swat a fly
> with a baseball bat -- a lot of machinery for what should be a more
> straightforward task. Of course, just because I think it **should be**
> straightforward does not mean it actually is. But I fooled around a bit
> (guided by Gabor's approach and an old Programmer's Niche column of Bill
> Venables) and came up with:
>
>> f <- lapply(e,function(x){do.call(substitute,list(x,list(b=z1)))})
>> f
> [[1]]
> [1] 0
>
> [[2]]
> a * (1/t)
>
>> ## f is a list. Turn it back into an expression
>> f <- as.expression(f)
>> ## check that this works as intended
>> f
> expression(0, a * (1/t))
>> a <- 2
>> t <- 3
>> eval(f)
> [1] 0.6666667
>
> Now you'll note that to do this I explicitly used quote() to produce the
> variable holding the subexpression to be substituted. You may ask, why not
> use expression() instead, as in
>
>> z2 <- expression(1/t)
>
> This doesn't work:
>
>> f <- lapply(e,function(x){do.call(substitute,list(x,list(b=z2)))})
>> f
> [[1]]
> [1] 0
>
> [[2]]
> a * expression(1/t)
>
>> f <- as.expression(f)
> ## Yielding ...
>> f
> expression(0, a * expression(1/t)) #### Not what we want!
> ## And sure enough ...
>> eval(f)
> Error in a * expression(1/t) : non-numeric argument to binary operator
>
> I think I understand why the z <- expression() approach does not work; but
I
> do not understand why the z <- quote() approach does! The mode of the
return
> from both of these is "call", but they are different (because identical()
> tells me so). Could someone perhaps elaborate on this a bit more? And is
> there a yet simpler and more straightforward way to do the above than what
I
> proposed?
>
> Cheers,
>
> Bert Gunter
> Genentech Nonclinical Statistics
>
>
> -----Original Message-----
> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org]
On
> Behalf Of Gabor Grothendieck
> Sent: Friday, January 29, 2010 11:01 AM
> To: Jennifer Young
> Cc: r-help at r-project.org
> Subject: Re: [R] evaluating expressions with sub expressions
>
> The following recursively walks the expression tree.  The esub
> function is from this page (you may wish to read that entire thread):
> http://tolstoy.newcastle.edu.au/R/help/04/03/1245.html
>
> esub <- function(expr, sublist) do.call("substitute", list(expr, sublist))
>
> proc <- function(e, env = parent.frame()) {
>   for(nm in all.vars(e)) {
>      if (exists(nm, env) && is.language(g <- get(nm, env))) {
>         if (is.expression(g)) g <- g[[1]]
>            g <- Recall(g, env)
>            L <- list(g)
>            names(L) <- nm
>             e <- esub(e, L)
>          }
>        }
>     e
> }
>
> mat <- expression(0, f1*s1*g1)
> g1 <- expression(1/Tm)
> vals <- data.frame(f1=1, s1=.5, Tm=2)
> e <- sapply(mat, proc)
> sapply(e, eval, vals)
>
> The last line should give:
>
>> sapply(e, eval, vals)
> [1] 0.00 0.25
>
>
> On Fri, Jan 29, 2010 at 11:51 AM, Jennifer Young
> <Jennifer.Young at math.mcmaster.ca> wrote:
>> Hallo
>>
>> I'm having trouble figuring out how to evaluate an expression when one of
>> the variables in the expression is defined separately as a sub
expression.
>> Here's a simplified example
>>
>> mat <- expression(0, f1*s1*g1)  # vector of formulae
>> g1 <- expression(1/Tm)          # expansion of the definition of g1
>> vals <- data.frame(f1=1, s1=.5, Tm=2) # one set of possible values for
>> variables
>>
>> before adding this sub expression I was using the following to evaluate
> "mat"
>>
>> sapply(mat, eval, vals)
>>
>> Obviously I could manually substitute in 1/Tm for each g1 in the
>> definition of "mat", but the actual expression vector is much longer, and
>> the sub expression more complicated. Also, the subexpression is often
>> adjusted for different scenarios.  Is there a simple way of changing this
>> or redefining "mat" so that I can define "g1" like a macro to be used in
>> the expression vector.
>>
>> Thanks!
>> Jennifer
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide
> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide
http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
>



More information about the R-help mailing list