An R bquote example

In this post I provide a simple example on the use of bquote in R. One context in which this function is highly useful is in the generation of a set of multiple well-annotated plots. We may want to plot a series of graphs and perhaps save each to disk as a jpeg for example. Each plot might have a unique title at the top. Let’s say that the titles follow a pattern such as “Plot 1”, “Plot 2”, “Plot 3”, etc. It is easy enough to sequentially plot and/or save your graphics using a for loop, and to use paste to annotate the plots appropriately:

for(i in 1:3) plot(0, 0, type="n", main=paste("Plot ",i,sep=""))

Simple enough. And annotations can become much more complicated and still be automated in a loop without much trouble. However, things become tricky if we want to move beyond simple character strings that can be easily pasted together. Say we wish to add mathematical symbols, which may require the use of expression. For example, to keep things simple, rather than looping over many plots, let’s use text to annotate one plot three times.

z1 <- c("A","B","C")

z2 <- c("high","med","low")

height <- c(0.5,0,-0.5)

plot(0,0,type="n")

Note that we do not actually make use of z1 or z2 yet below. It would be ideal, but that will come later.

text(0, height[1], labels=expression(Y[high] ~ "=" ~ A*x^2), cex=3)

text(0, height[2], labels=expression(Y[med] ~ "=" ~ B*x^2), cex=3)

text(0, height[3], labels=expression(Y[low] ~ "=" ~ C*x^2), cex=3)

Notice the use of expression. Rather than just entering a character string, or pasting multiple strings together, we wrap statements in expression. We pass an expression object to text. Not to deviate from the topic of bquote, as expression is worthy of its own discussion and tutorial on its varied uses, but we can see when plotting this that square brackets put their contents in subscript, the tilde operates as a separator and does not show up on our plot, the equal sign is the only thing quoted here, and the asterisk and caret are, expectedly, interpreted as mathematical expressions or operators, yielding the expected result on our plot.

The problem here is that how we wish to annotate plots as we iterate through a loop seems to preclude our ability to do any looping in the first place. How can we automate and streamline something like this? This will not work:
plot(0,0,type="n")

text(0,height[i],labels=expression(Y[z2[i]] ~ "=" ~ z1[i]*x^2),cex=3)

Ideally, during the ith iteration we would like z1 and z2 to be evaluated. We want to print the ith entry of z1 and z2 on our ith plot. We do not want to literally print "z1[i]", but this is precisely what happens. This is one place where bquote can be extremely helpful. It is short for backquote and essentially wraps quotes around whatever you pass to it. The catch is that anything passed to bquote that is itself wrapped in .() will be evaluated first. Notice below how we use bquote in place of expression and that everything else looks exactly the same as before with the exception that the two things we want to evaluate rather than print literally as displayed, z1[i] and z2[i], are wrapped in .() as required. We now can reproduce our original, desired result shown up above, but without having to hardcode each annotation.
plot(0,0,type="n")

for(i in 1:3) text(0, height[i], labels=bquote(Y[.(z2[i])] ~ "=" ~ .(z1[i])*x^2), cex=3)

The uses of bquote (and expression) go far beyond annotating plots and are useful in conjunction with many other R functions. But this is one clear example of how helpful it can be. The next time you have to write a set of graphics to disk, first and foremost spend some time annotating your graphics well, using symbols, subscripts, superscripts, font sizes, placement, etc. as appropriate. Secondly, don’t hardcode every plot. If you can make your plots sequentially in a loop, use these kinds of techniques to annotate them within the loop as well. It is often the case that people will forgo properly annotating their plots in the interest of expediency (a completely unnecessary tradeoff) or will slow themselves to a crawl doing everything by hand one plot at a time because they are unfamiliar with methods for setting up their annotations in a generic manner so that they can be applied in a more automated fashion.

This entry was posted by Matt Leonawicz.

2 thoughts on “An R bquote example

  1. Do I see correctly that bquote() substitutes for expression()?. The latter argument is not present in your last script-bit, is it not?

    • That is correct. In the last bit, expression() is not needed. bquote() is used in place and has the advantage of using .() to evaluate the z1 and z2 arguments, by using the square brackets for indexing the ith values. With expression, the square brackets would merely put their contents in subscript and the .() would not do any special evaluation first as it does in bquote().

      In R, an expression object is essentially a list or vector of one or more unevaluated calls. In the first bit we used expression to wrap unevaluated calls because we did not want to evaluate them. We just wanted them to be printed on the plot. Without expression() around the contents we would get all the expected complaints from R.

      bquote() takes an expression, an unevaluated call, as its main argument and we don’t need to do any explicit wrapping like bquote(expression()) or expression(bquote()). There are more complex situations where this explicit wrapping is necessary or useful, but at least for me this is very rare. I don’t have an example in front of me, but I know offhand that I have sometimes used nested calls like gsub(bquote(expression(…))) where expression() did have to be inside of bquote() due to the complexity of what I was trying to quote (I think I was trying to iteratively and automatically string together different pieces lots of complicated file names), But that leaves the word, “expression” in the quoted string that I then had to remove with gsub.

      I try to use expression() in general, since most of the time I only need to build a simple unevaluated expression to be evaluated later, such as placing a formula in a plot. I switch to bquote() usually if I am doing something iterative and don’t want to hard code one at a time the elements inside an expression that vary over the iterations. I may use both if the context of what I am doing makes the expression too complicated for bquote() to handle without it being stated explicitly as bquote(expression()).

      Matt

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: