5

I am trying to format a plot with two separate legends on the side. I have a shape legend, for all my different taxa, and a color legend, for the categories they belong in. I want to italicize only the taxon names in the shape legend, and not italicize the category names in the color legend. So far I can make all legend entries italicized or not using this line:

plot + theme(legend.text = element_text(face = "italic"))

But I don't know how to specify the shape legend only. I don't think theme() is appropriate because it changes the theme of the entire plot. I also looked into guides() but it doesn't seem to have an option for specifying font face of the legend labels.

Some sample data and a plot:

species <- c("M. mulatta", "P. ursinus", "C. mitis", "C. guereza")
subfam <- c("Cercopithecine", "Cercopithecine", "Cercopithecine", "Colobine")
x <- rnorm(4, 1:10)
y <- rnorm(4, 2:20)
df <- data.frame(cbind(species, subfam, x, y))

ggplot(df, aes(x, y)) + geom_point(aes(shape = species, color = subfam), size = 4) +
  labs(shape = "Species", color = "Subfamily")

In sum, I would like to make the species names italicized but not the subfamily names. It seems like it should be simple... Is this even possible in ggplot?

Thanks in advance!

Henrik
  • 65,555
  • 14
  • 143
  • 159
Julia
  • 53
  • 1
  • 4
  • This is quite difficult, involving the manipulation of the raw graphical objects (grobs) before plotting. I'd be inclined to use facets for subfamily and color for species, thus generating only one legend: `library(tidyverse); df %>% rename(Species = species, Subfamily = subfam) %>% ggplot(aes(x, y)) + geom_point(aes(color = Species)) + facet_wrap(~Subfamily) + theme(legend.text = element_text(face = "italic"))`. – neilfws Feb 01 '18 at 22:30

1 Answers1

6

You can customize labels specifically for the shape legend, by setting element_text parameters, including font, in scale_shape_discrete*.

ggplot(df, aes(x, y)) +
  geom_point(aes(shape = species, color = subfam), size = 4) +
  labs(shape = "Species", color = "Subfamily") +
  scale_shape_discrete(guide =
                         guide_legend(label.theme = element_text(angle = 0, face = "italic")))

enter image description here


*This method also works with scale_shape_manual, which also has a guide argument. See ?scale_shape and ?scale_shape_manual.


For some reason I needed to specify angle in element_text, otherwise it errored. You may also need to set size.

Henrik
  • 65,555
  • 14
  • 143
  • 159
  • This is a great solution! Unfortunately, there's another component in my real data that I didn't anticipate affecting the solution and so didn't include it in my original question. I actually have 22 taxa, and scale_shape_discrete() only allows up to 6 different shapes. I originally had scale_shape_manual() to specify the 22 shapes (which I think are perfectly discernible), but the two calls don't work together to produce the desired results. Any thoughts on how to make them both work? Thanks~ – Julia Feb 02 '18 at 02:31
  • In `ggplot` you can only have one call to `scale_xxx` per `aes`thetic. Thus, in you case you need to replace `scale_shape_discrete` with `scale_shape_manual`, which takes the same arguments, including `guide`. – Henrik Feb 02 '18 at 07:39
  • I had tried to add the manual shape values to scale_shape_discrete which didn't work; I forgot to consider the alternative of specifying guide in scale_shape_manual. Works perfectly, thank you! – Julia Feb 02 '18 at 13:50