41

I'd like to add a footnote citation to my 3-panel facet grid plot produced in R. It's a footnote to credit the data source. I'd ideally like to have it below and external to all three axes---preferably in the lower left.

I'm using ggplot2 and also ggsave(). This means I can't use grid.text()-based solutions, because that only draws on the x11() window, and can't be added to the ggplot object.

Using instead png() ...code... dev.off() does not appear to be an option because I need ggsave's resizing parameters, and find this command produces better, clearer prints (that are also much faster, because I'm not printing to the screen).

Here's my basic code:

p1 <- ggplot(data, aes(date, value))
    facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) + 
    theme_bw() +
        opts(title=mytitle)
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)

I've tried:

p1 <- ggplot(data, aes(date, value))
    facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) + 
    theme_bw() +
        opts(title=mytitle)
print(p1)
grid.text(unit(0.1,"npc"),0.025,label = "Data courtesy of Me")
grid.gedit("GRID.text", gp=gpar(fontsize=7))
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)

This appropriately puts the footnote in the lower left corner on the x11() display, external to the plots, but unfortunately, since it isn't applied to the p1 object, it isn't saved by the ggsave command.

I've also tried:

p1 <- ggplot(data, aes(date, value))
    facet_grid(variable ~ .) + geom_point(aes(y =value), size=1) + 
    theme_bw() +
    opts(title=mytitle) +
annotate("text", label = "Footnote", x = 0, y = 10, size = 5, colour = "black") +
print(p1)
ggsave("FILE.png",width=mywidth, height=myheight, p1, dpi=90)

This successfully prints using ggsave, however it has the following problems:

  • It is repeated 3 times, in each of the 3 facets, rather than 1 time.
  • It is contained within the plots, rather than external to them.
  • Text is difficult to place---seems to be using plot units (my x-axis is date, so 0 puts it around 1970).
  • The text size doesn't seem to change despite my size parameter.

A couple of related links from when I explored this...

Community
  • 1
  • 1
Mittenchops
  • 18,633
  • 33
  • 128
  • 246

3 Answers3

74

ggplot2 now has this ability natively with no need for additional packages. ... + labs(caption = "footnote", ...)

library(ggplot2) 
ggplot(diamonds, aes(carat, price, color = clarity)) + 
  geom_point() + 
  labs(title = "Diamonds are forever...", 
       subtitle = "Carat weight by Price", 
       caption = "H. Wickham. ggplot2: Elegant Graphics for Data Analysis Springer-Verlag New York, 2009.")

enter image description here

Brandon Bertelsen
  • 43,807
  • 34
  • 160
  • 255
38
library(gridExtra)
library(grid)
library(ggplot2)

g <- grid.arrange(qplot(1:10, 1:10, colour=1:10) + labs(caption="ggplot2 caption"), 
              bottom = textGrob("grid caption", x = 1, 
                                hjust = 1, gp = gpar(fontface = 3L, fontsize = 9)))
ggsave("plot.pdf", g)

enter image description here

Edit: note that this solution is somewhat complementary to the recent caption argument added to ggplot2, since the textGrob can here be aligned with respect to the whole figure, not just the plot panel.

baptiste
  • 75,767
  • 19
  • 198
  • 294
  • This approach does not seem to work for gridExtra_0.8.1 and ggplot2_0.9.3.1 with the error message `Error in switch(ct, ggplot = ggplotGrob(grobs[[ii.table]]), trellis = latticeGrob(grobs[[ii.table]]), : EXPR must be a length 1 vector` – russellpierce Mar 06 '13 at 21:44
  • 1
    that's why you should update gridExtra to the current version – baptiste Mar 06 '13 at 22:05
  • Fantastic how-to article based on this question: http://bigdata-analyst.com/best-way-to-add-a-footnote-to-a-plot-created-with-ggplot2.html – Tom Aug 25 '14 at 02:05
  • 1
    This seems to be broken with the 2.0.0 version of gridExtra–the `sub =` argument is no longer supported, and `arrangeGrob()` returns a TableGrob rather than a ggplot-inherited object. – Tom Jul 20 '15 at 15:21
  • 2
    @Tom The dev version of ggplot2 now allows `ggsave` to save the object from `arrangeGrob()`. See [commit](http://stackoverflow.com/a/18407452/3429373). – BeingQuisitive Aug 02 '15 at 14:12
  • 4
    Given the re-write of gridExtra by the package author (same author of this answer), the provided solution is no longer possible with the most recent gridExtra package. You can do something like this: grid.arrange(g, ncol=1, bottom = "footnote") – yokota Jan 03 '16 at 08:15
  • @user2434624 your comment puzzles me: I edited the answer last July – baptiste Jan 03 '16 at 20:38
  • I find the answer below with the `labs(caption = ...)` answer to be the easiest and most "native" ggplot2 solution. – Nicholas G Reich Jul 22 '20 at 14:01
12

Adding to the answer of Brandon Bertelsen: if you want to have the caption in the left corner, add

theme(plot.caption = element_text(hjust = 0))
MartineJ
  • 591
  • 5
  • 16