4

I'm using ggplot to do some multiline plots that are constructed with lots of variables and the use of paste. I have not been able to figure out how to get the subscript 3 in O3 to appear in the following simplified version of the code.

gasSubscript <- "O[3]"
color1 <- paste(gasSubscript,"some additional text")
df <- data.frame(x = c(1,2,3,4,5,6,7,8,9,10), y = c(10,9,8,7,6,5,4,3,2,1))
testPlot <- ggplot(data = df, aes(x = x)) + geom_line(aes(y = y, color = color1))

color1 contains

  "O[3] some additional text"

The legend displays as "O[3] some additional text" rather than with a subscripted 3.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • If [this](http://stackoverflow.com/q/6202667/324364) question doesn't answer your question, can you explain in detail why? – joran May 01 '15 at 21:02
  • In the question/answer you linked to, the relevant line of code is "labels=c(expression(b[1]), expression(c[1])". I would like to replace "expression(b[1]" with a variable that includes O[3] and have this interpreted as O subscript 3. I can't figure out how to make this happen. – Gerald Nelson May 02 '15 at 23:21
  • You'll have to convert the text to an expression yourself at some point. There's no other way that I know of. – joran May 02 '15 at 23:30

2 Answers2

6

The problem is that you need the label in the scale to be an expression so that, when it is rendered, it is rendered according to the rules of plotmath. However, ggplot works with data.frames and data.frames can not have a column which is a vector of expressions. So the way around this is to store the information as the text (string) version of the plotmath expression and, as the last step for making the labels, turn these into expressions. This can be done because the labels argument to the scale functions can itself be a function which can transform/format the labels.

Putting this together with your example:

color1 <- paste(gasSubscript,"*\" some additional text\"")

This is now in a format that can be made into an expression.

> color1
[1] "O[3] *\" some additional text\""
> cat(color1)
O[3] *" some additional text"
> parse(text=color1)
expression(O[3] *" some additional text")

With that format, you can force the scale to interpret the labels as expressions which will cause them to be rendered as per the rules of plotmath.

testPlot <- ggplot(data = df, aes(x = x)) + 
  geom_line(aes(y = y, color = color1)) +
  scale_colour_discrete(labels = function(x) parse(text=x))

enter image description here

Using the labels function approach works for data which is stored in the data.frame as well, so long as the strings are formatted so that they can be parsed.

DF <- data.frame(x=1:4, y=rep(1:2, times=2), 
                 group = rep(c('O[3]*" some additional text"', 
                               'H[2]*" some different text"'), each = 2))

ggplot(DF, aes(x, y, colour=group)) + 
  geom_line() +
  scale_colour_discrete(labels=function(x) parse(text=x))

enter image description here

Brian Diggs
  • 57,757
  • 13
  • 166
  • 188
  • This works. Thanks! But I really don't understand the logic. I suspect it is lack of understanding about the complexities of ggplot2. Given these complexities and the fact that I will probably want to use it a lot, can you recommend a source or two (book, link) that provide some more in depth explanation. Amazon has a bunch of books that purport to do this so my problem is choice anxiety! – Gerald Nelson May 03 '15 at 17:58
  • @GeraldNelson I can not personally recommend any particular book. I didn't learn from a book because there weren't any at the time. – Brian Diggs May 04 '15 at 06:49
  • This works, but aligns all labels to the right, which looks weird if you have multiple labels. – User878239 Feb 05 '20 at 22:09
0

This should do what I think you want. It took me a little tinkering to get the right order of paste and expression.

require(ggplot2)
test <- data.frame(x = c(1,2,3,4,5,6,7,8,9,10), y = c(10,9,8,7,6,5,4,3,2,1))
colour1 <- "1"

testPlot <- ggplot(data = test, aes(x = x)) + geom_line(aes(y = y, colour = colour1))
testPlot + scale_colour_discrete(labels = c(expression(paste(O[3], "some other text here"))))

Subscript legend label

It also returns the warning

Warning message:
In is.na(scale$labels) :
  is.na() applied to non-(list or vector) of type 'expression'

to which I haven't been able to find an explanation.

r.bot
  • 5,309
  • 1
  • 34
  • 45
  • This answer doesn't do it for me. I need to have the variable gasSubscript interpreted, rather that putting the code that defined gasSubscript (paste(O[3], "some other text here")) into the expression code. – Gerald Nelson May 02 '15 at 23:15