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)
Note that we do not actually make use of
z2 yet below. It would be ideal, but that will come later.
text(0, height, labels=expression(Y[high] ~ "=" ~ A*x^2), cex=3)
text(0, height, labels=expression(Y[med] ~ "=" ~ B*x^2), cex=3)
text(0, height, 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
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:
text(0,height[i],labels=expression(Y[z2[i]] ~ "=" ~ z1[i]*x^2),cex=3)
Ideally, during the ith iteration we would like
z2 to be evaluated. We want to print the ith entry of
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,
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.
for(i in 1:3) text(0, height[i], labels=bquote(Y[.(z2[i])] ~ "=" ~ .(z1[i])*x^2), cex=3)
The uses of
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.