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-boun...@r-project.org [mailto:r-help-boun...@r-project.org] On Behalf Of Gabor Grothendieck Sent: Friday, January 29, 2010 11:01 AM To: Jennifer Young Cc: r-help@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.yo...@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@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@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@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.