9

How can I have multiple colors for an axes label in ggplot?

As an example, instead of a legend, I would like the y-axis label to be red and green to correspond to the different points in the following plot:

p <- ggplot(mpg[mpg$model=="a4",],aes(x=trans,y=cty))+geom_point(color="red")+
     geom_point(aes(y=hwy),color="dark green") +
     ylab("MPG (city); MPG (hwy)")

I know I can control the color of the entire y-axis label using theme as follows:

p <- p + theme(axis.title.y = element_text(color="red"))

But, in the plot I want the "MPG (hwy)" to be in dark green. Is there a way to do this in ggplot?

Ferdi
  • 540
  • 3
  • 12
  • 23
cfosser
  • 155
  • 2
  • 5
  • 1
    I don't think it's can be done without some very nasty abuse of `ggplot` syntax. But maybe just adding a legend will help? Something like `library(reshape2); temp <- melt(mpg[mpg$model=="a4", c("trans", "cty", "hwy")], id.vars = "trans"); ggplot(temp, aes(x = trans, y = value, color = variable)) + geom_point() + scale_colour_manual(values = c("red", "dark green")) + ylab("MPG (city); MPG (hwy)")` – David Arenburg Aug 03 '14 at 13:20

2 Answers2

11

I don't think you should abuse an axis title as a legend, but you can do this at the grid level:

library(ggplot2)

p <- ggplot(mpg[mpg$model=="a4",],aes(x=trans,y=cty))+
  geom_point(color="red")+
  geom_point(aes(y=hwy),color="dark green") +
  ylab("MPG (city); MPG (hwy)")

g <- ggplotGrob(p)

g[[1]][[7]]$label <- c("MPG (city);",  "MPG (hwy)")
g[[1]][[7]]$gp$col <- c("red", "dark green")
library(grid)
g[[1]][[7]]$y <- unit(c(0.45, 0.54), "npc")
#fiddle with the coordinates until the positioning fits for your specific strings

plot(g)

enter image description here

Of course it would be preferable to simply create a legend by using proper mapping of the color variable.

Update

With ggplot2 v2.2.1 this needs to be adjusted since the gtree has changed. Now this works:

#g[[1]] shows which grob is the y axis title
#then use str to see the structure of the grop
#you can also use grid.edit instead but I find the following more easy
g[[1]][[13]]$children[[1]]$label <- c("MPG (city);",  "MPG (hwy)")
g[[1]][[13]]$children[[1]]$gp$col <- c("red", "dark green")
g[[1]][[13]]$children[[1]]$hjust <- c(1, 0)
g[[1]][[13]]$children[[1]]$y <- unit(c(0.5, 0.5), "npc")

plot(g)
Community
  • 1
  • 1
Roland
  • 127,288
  • 10
  • 191
  • 288
  • 1
    I get this error: `Error in set.gpar(x$gp) : argument must be a 'gpar' object`. Is there a workaround? – Garini May 08 '18 at 07:43
  • Yes, pass a gpar object. The inner workings of ggplot2 have changed a lot in the last four years. – Roland May 08 '18 at 07:48
  • Can I ask you how? I am not really confident with `gpar` and my trials failed till now. – Garini May 08 '18 at 08:17
  • I am using v2.2.1.9000 and the error is still there. It does not plot anything – Garini May 08 '18 at 09:44
  • Likely you'll need to check what the internal structure is now (see my comment regarding `str`). I won't install the development version. – Roland May 08 '18 at 10:11
3

Extending David Arenburg's comment, this gets a little closer without getting into the grid level:

library(reshape2)  # easier to group by color with melted data

temp <- melt(mpg[mpg$model=="a4", c("trans", "cty", "hwy")], id.vars = "trans")

making label strings identified by the same variable for grouping:

labs <- data.frame(variable = c("cty", "hwy"), 
                   value = c("MPG (city); ", "MPG (hwy) "), 
                   y = c(22,26))  # vertical position for labels



p <- ggplot(temp, aes(x=trans, y=value, color=variable)) +
  geom_point() + 
  geom_text(data = labs, angle = 90, # add rotated text near y-axis
            aes(x = 0.5, y = y, label = value)) +
  scale_color_manual(values=c("red", "dark green"), guide = "none") +
  ylab("") # hide default y-axis label

Who says y-axis can't be labeled on the right side, anyhow?

2-color y-axis label

Scott
  • 765
  • 4
  • 9