Skip to content

Names of Greek letters stored as character strings; plotmath.

18 messages · Rolf Turner, Gabor Grothendieck, Paul Johnson +6 more

#
I had such good luck with my previous question to r-help, (a few minutes
ago) that I thought I would try again with the following query:
Then, just before clicking on "Send", I had one more thimk, and blow
me down, I got something that worked:

plot(1:10,xlab=eval(expression(parse(text=xNm))))

This is another counter example to my colleague Thomas Lumley's dictum
expressed in fortune("parse").  :-)

I had to try several permutations of "eval" and "expression" and "parse",
but I finally found that the permutation presented above does what I want.
(Clearly I have no real idea what I'm doing, just hammering and hoping,
but it's amazing how far hammer and hope will get you sometimes with R!)

Just thought I'd post this in case it might be helpful to others.  Also 
to see
if anyone can tell me a better/slicker/sexier way to get to the same result.

     cheers,

             Rolf Turner
#
On Sat, May 19, 2012 at 1:18 AM, Rolf Turner <rolf.turner at xtra.co.nz> wrote:
That can be shortened to:

plot(0, xlab = parse(text = xNm))
#
... and here is another incantation that may be  informative.

xnm<- as.name("gamma')  ## This does the parsing
plot(0, xlab =bquote(.(xnm))

The initial puzzle is that if you just set
xnm <- "gamma"

bquote will insert the string "gamma" rather than the symbol. After
all, that's what plotmath sees for xnm. So the key is telling plotmath
that it's a symbol, not a string. This can either be done before, as
above, or inline, as you and Gabor showed. Unsurprisingly. this also
does it, since as.name() is doing the parsing:

xnm <- "gamma"
 plot(0,xlab=bquote(.(as.name(xnm))))

AND we are adhering to Thomas's dictum: bquote is a wrapper for
substitute(), which is what he recommends as the preferable
alternative to eval(parse(...)) . But, heck -- all such software
principles are just guidelines. Whatever works (robustly).

HTH.

Cheers,
Bert

On Sat, May 19, 2012 at 3:17 AM, Gabor Grothendieck
<ggrothendieck at gmail.com> wrote:

  
    
#
..and a final addendum:

xnm <- quote(gamma)
## makes xnm the name gamma not the string "gamma"

plot(0,xlab = bquote( .(xnm))

-- Bert
On Sat, May 19, 2012 at 7:23 AM, Bert Gunter <bgunter at gene.com> wrote:

  
    
#
parse(text=paste(...)) works in simple cases but not in others.  The
fortune about it is there because it is tempting to use but if you bury it
in a general purpose function it will cause problems when people
start using nonstandard names for variables.  bquote(), substitute(),
call(), and relatives work in all cases.  E.g.,

  > par(mfrow=c(2,1))
  > power <- "gamma" ; x <- "Waist" ; y <- "Weight" # valid R variable names
  > plot(0, main=bquote(.(as.name(x))^.(as.name(power))/.(as.name(y))))
  > plot(0, main=parse(text=paste0(x, "^", power, "/", y))) # same as previous
  >
  > power <- "gamma" ; x <- "Waist Size (cm)" ; y <- "Weight (kg)" # invalid R names
  > plot(0, main=bquote(.(as.name(x))^.(as.name(power))/.(as.name(y))))
  > plot(0, main=parse(text=paste0(x, "^", power, "/", y))) # whoops
  Error in parse(text = paste0(x, "^", power, "/", y)) :
    <text>:1:7: unexpected symbol
  1: Waist Size
           ^

Now you might say that serves me right for using weird variable names,
but some of us use R as a back end to a GUI system (one not designed
around R) and don't want to inflict on users R's rules for names when
we do not have to.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
On Sat, May 19, 2012 at 11:07 AM, William Dunlap <wdunlap at tibco.com> wrote:
Bill's point is on the money here. We should aim to teach one way that
works always. But finding that one way is the hard part for me.

Lately, I'm bothered that R (or computers in general?) allows too many
ways to do the same thing that work SOME of the time. Without a very
deep understanding of the terminology, users are bewildered.

Go read ?plotmath.  Do we see "as.name"?   NO.  Why does the idiom
expression(paste()) work as well?   (Don't answer, that's a rhetorical
question).

There are too many ways to do the same thing. Or, well, too many of us
know one way that works sometime and don't find out it doesn't always
work until, as Bill says, it is buried in the bottom of some big
function that behaves erratically.

Gabor notes this works (sometimes):

plot(0, xlab = parse(text = xNm))

Bert observes this works (sometimes)

xnm <- quote(gamma)
## makes xnm the name gamma not the string "gamma"
plot(0,xlab = bquote( .(xnm))

Bill observes this works:
xnm <- "gamma"
plot(0,xlab = bquote(.(as.name(xnm))))

In line with that, Bill suggests:

power <- "gamma" ; x <- "Waist Size (cm)" ; y <- "Weight (kg)" # invalid R names
plot(0, main=bquote(.(as.name(x))^.(as.name(power))/.(as.name(y))))

It appears to me that 2/3 of the as.name usages are not needed, at
least not in R 2.15 on Debian Linux.

This works just as well

plot(0, main=bquote(.(x)^.(as.name(power))/.(y)))


Is there any important reason to wrap x and y in this command with as.name?

It does work, maybe I be in the general habit of wrapping as.name
around variables in bquotes?  I'm more confused.

The good new for me is that I cannot find any replacements for the
usage of "as.name" in that particular expression. So there is just one
way.

Oh, wait, I spoke too soon. as.symbol is identical to as.name.

plot(0, main=bquote(.(x)^.(as.symbol(power))/.(y)))

And then, logically, this works:

plot(0, main=bquote(.(x)^.(as.vector(power, "symbol"))/.(y)))

I personally think "as.symbol" is more likely to be understood by
students, I may stick to that. So I think the most succinct, best
approach is


plot(0, main=bquote(.(x)^.(as.symbol(power))/.(y)))

or perhaps the most consistent-looking strategy is:

power <- as.symbol("gamma") ; x <- "Waist Size (cm)" ; y <- "Weight (kg)"
plot(0, main=bquote(.(x)^.(power)/.(y)))

Speaking of commands that have identical results and exist separately
for no apparently good reason:

library(help=rockchalk)

help(package=rockchalk)

pj

  
    
#
On Sat, May 19, 2012 at 2:16 PM, Paul Johnson <pauljohn32 at gmail.com> wrote:
Actually, I was pointing out that that expression was as good as a
longer expression that was posted and it always works (not just
sometimes) if one interprets the problem as supplying the character
representation of a plotmath expression in xNm -- this seems the
logical generalization given that the example was the character
representation of a plotmath expression.
#
Paul Johnson wrote
The return value of bquote is different in those 2 cases (with and without
the as.name):
   > bquote(.(as.name(x))^.(as.name(power))/.(as.name(y)))
   `Waist Size (cm)`^gamma/`Weight (kg)`
   > bquote(.(x)^.(as.name(power))/.(y))
   "Waist Size (cm)"^gamma/"Weight (kg)"
However, plotmath doesn't print the quotes around a string like
"Weight (kg)", nor the backticks around a weird name like `Weight (kg)`,
 so you don't notice the difference when using bquote's output for plotmath.
If you were constructing a formula for lm() then you would notice the difference.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
Many thanks to Baptiste Auguie (off list), Bill Dunlap, Bert Gunter, 
Gabor Grothendieck,
and Paul Johnson for their interesting and informative responses to my post.

The main item to note is that I was piling on unnecessary baggage by using

     plot(1:10,xlab= eval(expression(parse(text=xNm))))

Just the "parse()" bit is all that is necessary:

     plot(1:10,xlab=parse(text=xNm))

accomplishes the same task and is much simpler.

I have taken note of, and stored away for future reference, the suggestions
for the use of substitute, bquote, quote, as.name and as.symbol.  I am 
particularly
grateful for Bert Gunter's explanation of why

     xNm <- "gamma"
     plot(1:10,xlab= bquote(.(xNm))

yields the string "gamma" rather than the symbol consisting of the Greek 
letter
gamma.

I am also very grateful for Bill Dunlap's example of how things can go wrong
with parse.

I sympathise with Paul Johnson's complaint that there are often too many 
ways
to accomplish the same task and that sometimes some ways work in some
contexts but not in others.  However it seems to me that we're just 
stuck with
this.  There is no way to make a perfect programming language --- perfection
just doesn't exist.  From my POV, R comes as close to the ideal as one can
reasonably expect.  The fact that R is constantly growing and developing
contributes to the fact that ways to accomplish the same task proliferate,
but its growth and development are such an asset that we must (cheerfully!)
just live with the attendant drawbacks.

Again, thanks to all.

     cheers,

         Rolf Turner
#
-----Original Message----- 
From: William Dunlap
Sent: Saturday, May 19, 2012 11:07 AM
To: Rolf Turner
Cc: r-help
Subject: Re: [R] Names of Greek letters stored as character 
strings;plotmath.

parse(text=paste(...)) works in simple cases but not in others.  The
fortune about it is there because it is tempting to use but if you bury it
in a general purpose function it will cause problems when people
start using nonstandard names for variables.  bquote(), substitute(),
call(), and relatives work in all cases.  E.g.,

  > par(mfrow=c(2,1))
  > power <- "gamma" ; x <- "Waist" ; y <- "Weight" # valid R variable names
  > plot(0, main=bquote(.(as.name(x))^.(as.name(power))/.(as.name(y))))
  > plot(0, main=parse(text=paste0(x, "^", power, "/", y))) # same as 
previous
  >
  > power <- "gamma" ; x <- "Waist Size (cm)" ; y <- "Weight (kg)" # invalid 
R names
  > plot(0, main=bquote(.(as.name(x))^.(as.name(power))/.(as.name(y))))
  > plot(0, main=parse(text=paste0(x, "^", power, "/", y))) # whoops
  Error in parse(text = paste0(x, "^", power, "/", y)) :
    <text>:1:7: unexpected symbol
  1: Waist Size
           ^

Now you might say that serves me right for using weird variable names,
but some of us use R as a back end to a GUI system (one not designed
around R) and don't want to inflict on users R's rules for names when
we do not have to.

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
-- snip --


This discussion has been exceedingly helpful, sort of.

Every time I try to do a task involving this I read the documentation for 
bquote(), expression(), plotmath(), etc.,  over and over, and I still fail 
to get the big picture of how R parses things under the hood.  Typically, I 
only succeed each time by frustrating trial and error.   Can I ask how you 
guys got a handle on the bigger (besides your usual brilliance <G>)?

Is there more comprehensive documentation in the developer literature or is 
there a user wiki that you would recommend for those who never quite get the 
big picture?  If not, this would be a worthy topic for an R Journal article 
if someone has knowledge and the time to do it.  Wish I were knowledgeable 
enough to do it myself.

Thanks,

Rob
______________________________________________
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.


------------------------------------------
Robert W. Baer, Ph.D.
Professor of Physiology
Kirksville College of Osteopathic Medicine
A. T. Still University of Health Sciences
800 W. Jefferson St.
Kirksville, MO 63501
660-626-2322
FAX 660-626-2965
#
On 21/05/12 10:53, Robert Baer wrote:
<SNIP>
Amen.  My experience/reaction exactly.

I think though that the concepts involved are really truly subtle and it may
be difficult for the brilliant guys to explain them in such a way that 
those of
us who are less brilliant can understand them.

     cheers,

         Rolf
#
On 12-05-20 6:53 PM, Robert Baer wrote:
I think you have to try writing C code to work with R objects to really 
understand what's going on.  Reading those sections of the Writing R 
Extensions manual will probably help, but actually writing C code to do 
it may be necessary.

It's not really a very complicated system, it's just that things that 
are obviously different in C (e.g. the R symbol name "gamma" versus the 
string "gamma") look confusingly similar in R.

You might be able to figure this out by studying the result of str(x) 
(or the low level .Internal(inspect(x))) for lots of different x 
objects, but I don't think it's going to make sense unless you know 
what's going on behind the curtain.

Duncan Murdoch
#
Well, that's not very comforting, Duncan. It's like saying that you
have to read the engineering specs to drive the car successfully.

I am certainly ignorant of the internals, but I honestly believe
well-written documentation on these points would help. I learned a lot
when I read V&R's "S Programming" some years ago, so I think that's an
existence theorem.

Unfortunately, writing such documentation is hard, maybe harder than
writing the code even (my own experience documenting my own code). And
your logical response -- "Bert, R is open source and would welcome
your efforts" -- is not going to get much traction. Like you, I don't
have the time (nor, in my case, the smarts).

Nevertheless, I agree with Robert's sentiment that it could be done.
In particular, plotmath docs really should expand their explanation of
appropriate syntax, imho.

As always, I end by acknowledging the extraordinary efforts of R's
developers. Your success is what has led to such carping. A response
of "Aw shaddup" would therefore not be out of line.

Best,
Bert

On Sun, May 20, 2012 at 5:00 PM, Duncan Murdoch
<murdoch.duncan at gmail.com> wrote:

  
    
#
This may be a profoundly bad idea, but if deduction is beyond the skill of those with time, perhaps an inferential approach could be used.  Create examples of when one approach versus another works.  A book of spells, if you will, so that rather than hoping and typing wildly, the magic incantation can simply be looked up.

Josh
On May 20, 2012, at 19:28, Bert Gunter <gunter.berton at gene.com> wrote:

            
#
On 12-05-20 10:28 PM, Bert Gunter wrote:
I think Robert's message that I responded to was asking for a deeper 
understanding than simply driving the car.  He appeared to want to know 
why the car worked the way it did, and describing that entirely in terms 
of things you can see without opening the hood is hard.
I wouldn't disagree with that.  Both V and R knew an awful lot about S 
when they wrote that, and they know how to communicate well.
I don't think it's impossible to write the book Robert wants, and since 
there are a lot of R books out there, someone may have already done it. 
If they have, maybe they did it by explaining R internals.  If not, I 
think my advice stands.

Duncan Murdoch
#
On May 21, 2012, at 05:25 , Duncan Murdoch wrote:

            
There are levels, though. For basic car driving, it might be sufficient to know that turning the steering wheel left makes the car change direction towards left. Rather soon, you will realize that it is imortant that it does so by turning the front wheels; this explains why you need to reverse into a parallel-parking space. At some point, it may become useful to know that the wheels are tangential to the curve that the car follows and that it therefore turns around a point on the line trough the rear wheels (not that that ever helped me to parallel park...).

In R, it is important to have some reasonably accurate mental image of its internal structures. For quote() and friends, the thing that you really need is the notion of a _parse tree_, i.e. the fact that expressions are not evaluated as-is, but first converted (parsed) to an internal structure that is equivalent to a list of lists:
`/`
[1] 2
(3 + a)
`(`
3 + a
`+`
[1] 3
a

or, graphically (mailer permitting)

`/` +--2
    |
    +--`(`--`+` +-- 3
                |
                +-- a

Once you have this concept in mind, it should become fairly clear that the string constant "a" is fundamentally different from the variable name a.
#
I don't think the concepts are "truly subtle"; it is essentially the
difference between things and names of things (and names are
also things).   However, we have muddied the waters by providing
"convenience" functions like library() and help() and some plotmath
constructs that try to cover up the difference between a thing and
its name. 

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com
#
Yet again:Thank you Peter and Duncan. I appreciate your comments and insights.

I agree wholeheartedly with Peter's comments below about understanding
what a parsed expression is in R. In R -- and in functional
programming in general, I believe -- computing on the language is
extremely handy, even for relatively basic programming.  I found V&R's
discussion in "S Programming" on "Computing on the Language" very
helpful in this regard, especially their table 3.2,  which dissects
the different but cognate situation of formulas,  functions, and
function calls. Perhaps something similar could be done for
expression(), parse(), and quote(). I think there are subtleties here
that deserve explicit mention and elaboration.

As a feeble attempt in this direction, which I hope illuminates more
than it obfuscates -- and I would greatly appreciate prompt
corrections of any errors -- perhaps the following might be useful:
########################
a <- 3
x <- quote(a+2)
y <- parse(text = "a+2")
z <- expression(a+2)
##
eval(x) ## 5
eval(y) ## the same
eval(z) ## the same
##
## Now note:
as.list(x) ## quote(a+2) the parse tree for the expression a+2
##
as.list(y) ## looks like a list whose component is the parse tree for
the expression
## as demonstrated by:
##
identical(x,y[[1]]) ##TRUE
##
as.list(z) ## appears to be the same as z. And, indeed,
##
identical(y[[1]],z[[1]])  ##TRUE. The parse tree for the expression again.
##
### However
##
identical(y,z) ## FALSE !!
## To see what's going on, use str()
str(x) ## language a + 2
str(y[[1]]) ## the same
str(z[[1]]) ## the same
##
## But
str(y) ## complex structure with attributes
str(z) ## simple expression
##########################################

To me, this reinforces Bill Dunlap's and Thomas Lumley's counsels:
avoid explicit parsing and evaluation via eval(parse(...)) in favor of
working with the parsed expression via substitute() and bquote().

HTH,

Bert
On Mon, May 21, 2012 at 12:20 AM, peter dalgaard <pdalgd at gmail.com> wrote: