Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two subtitles, one left-aligned, one right-aligned, on the same line

Tags:

r

ggplot2

Using ggplot2, I'd like to have two subtitles on the same line, under the title, but one left-aligned and one right-aligned for a facetted plot like the one below.

enter image description here

I can have a subtitle left-aligned:

p <- ggplot(mtcars, aes(mpg, hp)) + 
  geom_point() +
  facet_grid(am~.) +
  theme(plot.title=element_text(hjust=0.5))

p + labs(title="Data: mtcars", subtitle="Subtitle (left-aligned)")

or right-aligned,

p + labs(title="Data: mtcars", subtitle="Subtitle (right-aligned)") +
  theme(plot.subtitle=element_text(hjust=1))

but I can't seem to have both, unless I combine them with an arbitrarily large number of spaces in between (which is how I made the plot above). But I don't like that solution. Is there another way?

like image 786
Edward Avatar asked Sep 18 '25 22:09

Edward


2 Answers

Hacky and spooky, but works. You can pass a vector to subtitle= and set the alignment for each element by passing a vector to hjust= (which of course is not officially supported):

library(ggplot2)

p <- ggplot(mtcars, aes(mpg, hp)) +
  geom_point() +
  facet_grid(am ~ .) +
  theme(plot.title = element_text(hjust = 0.5))

p + labs(
  title = "Data: mtcars",
  subtitle = c("Subtitle (left-aligned)", "Subtitle (right-aligned)")
) +
  theme(plot.subtitle = element_text(hjust = c(0, 1)))
#> Warning: Vectorized input to `element_text()` is not officially supported.
#> ℹ Results may be unexpected or may change in future versions of ggplot2.

like image 152
stefan Avatar answered Sep 20 '25 14:09

stefan


It's a bit of a fudge, but you could do something like this...

p + labs(title="Data: mtcars", subtitle = "") +
  geom_text(x = I(0), y = I(2.1), label = "left subtitle", hjust = 0) +
  geom_text(x = I(1), y = I(2.1), label = "right subtitle", hjust = 1) +
  coord_cartesian(clip = 'off')

or (better, as per Stefan's comment below), use annotate...

p + labs(title="Data: mtcars", subtitle = "") +
    annotate("text", x = I(0), y = I(2.1), 
             label = "left subtitle", hjust = 0) +  
    annotate("text", x = I(1), y = I(2.1), 
             label = "right subtitle", hjust = 1) +
    coord_cartesian(clip = 'off')

The blank subtitle argument just creates a bit of space. The final clip = "off" allows you to plot outside the normal plot area. The I(0) notation allows you to use relative coordinates where 0 is left/bottom and 1 is right/top. I had to use y=I(2.1) as you have two facets in your plot, so y=I(1) is the top of the lower facet.

enter image description here

like image 28
Andrew Gustar Avatar answered Sep 20 '25 14:09

Andrew Gustar