[R] evaluating expressions with sub expressions

Jennifer Young Jennifer.Young at math.mcmaster.ca
Sat Jan 30 16:39:42 CET 2010


Thanks so much everyone!

Bert's shorted example does what I need, but I'm filing away Gabor's
solution for when I inevitably need it some day.   I've never found the
handling of variables in R to be very straightforward; sometimes I pine
for Maple to do my algebra for me...

> 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]]))
>
> 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.
>
> For example, suppose mat[[2]] is a function of g1 which is a function
> of Tm which is a function of z.  Then continuing the example in the
> original post this does the repeated substitution needed (which would
> be followed by an eval, not shown here, as in my original post):
>
>> Tm <- expression(z^2)
>> sapply(mat, proc)
> [[1]]
> [1] 0
>
> [[2]]
> f1 * s1 * (1/z^2)
>
> 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.
>
> 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