David Hewitt
2009-Jan-27 21:47 UTC
[R] Plotmath and line breaks in long annotations for plots
I'm trying to combine multi-line text and math annotations on a plot and am not having much luck. I looked at various suggestions in the archives, but I cannot coerce any of them to do what I want. I'm beginning (finally?!) to think that there is an entirely better approach than the one I have tried. The essential problem is that line breaks (\n) don't seem to behave the way I expected when combined with text strings and plotmath in a call to text(). My vision for the annotation, which may be a little beyond the norm, is to have a series of centered lines of text somewhere on the plot that includes various object values and symbols. I'd like to wrap it all up in one call to text() so that it has a common anchor. Here is an example: a <- c(1, 10) b <- c(1, 10) amean <- mean(a) bmean <- mean(b) plot(a, b) # Annotation with paste() text(amean, bmean, bquote(paste("Here are the values\nI want to write on the plot\n\n", amean==.(amean), "\nand\n", bmean==.(bmean)))) # Annotation without paste() text(amean, bmean, bquote('Here are the values\nI want to write on the plot\n\n'~amean==.(amean)~'\nand\n'~bmean==.(bmean))) Another suggestion in the archives involved creating a list with the strings that were then passed through parse(), but that did not work either. Corrections, suggestions, or redirections greatly appreciated. -- Dave Hewitt Research Fishery Biologist US Geological Survey, Klamath Falls, OR, USA
Marc Schwartz
2009-Jan-27 22:49 UTC
[R] Plotmath and line breaks in long annotations for plots
on 01/27/2009 03:47 PM David Hewitt wrote:> I'm trying to combine multi-line text and math annotations on a plot > and am not having much luck. I looked at various suggestions in the > archives, but I cannot coerce any of them to do what I want. I'm > beginning (finally?!) to think that there is an entirely better > approach than the one I have tried. > > The essential problem is that line breaks (\n) don't seem to behave > the way I expected when combined with text strings and plotmath in a > call to text(). My vision for the annotation, which may be a little > beyond the norm, is to have a series of centered lines of text > somewhere on the plot that includes various object values and symbols. > I'd like to wrap it all up in one call to text() so that it has a > common anchor. Here is an example: > > a <- c(1, 10) > b <- c(1, 10) > amean <- mean(a) > bmean <- mean(b) > > plot(a, b) > > # Annotation with paste() > text(amean, bmean, > bquote(paste("Here are the values\nI want to write on the plot\n\n", > amean==.(amean), "\nand\n", bmean==.(bmean)))) > > # Annotation without paste() > text(amean, bmean, > bquote('Here are the values\nI want to write on the > plot\n\n'~amean==.(amean)~'\nand\n'~bmean==.(bmean))) > > Another suggestion in the archives involved creating a list with the > strings that were then passed through parse(), but that did not work > either. > > Corrections, suggestions, or redirections greatly appreciated.The root issue is that plotmath does not support newlines within the expressions to be output. You really need to create and output each line separately. As you will see below, it is possible to do it with a single call to text(). One can use the function strheight() to get a sense (in plot region user coordinates) as to how high a line of text would be. Then you can adjust the subsequent lines based upon this value. For example: a <- c(1, 10) b <- c(1, 10) amean <- mean(a) bmean <- mean(b) plot(a, b) # See ?strheight hght <- strheight("Here") # How high is a line of text?> hght[1] 0.2264324 Lines <- list("Here are the values", "I want to write on the plot", "", bquote(amean == .(amean)), "and", bquote(bmean == .(bmean))) # Now output each line # The text in the list is converted to expressions # using do.call(expression, Lines) # Adjust the y position value based upon multiplying 'hght' # by 1:4 and a scale adjustment (1.5) for spacing # subtract that from 'bmean' to place each line below # the prior one text(amean, bmean - (hght * 1.5 * seq(length(Lines))), do.call(expression, Lines)) HTH, Marc Schwartz