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.ber...@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-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.