Best way to add a footnote to a plot created with ggplot2

There are different kinds of tools for data visualization and ggplot2 is always my favorite. It is powerful, elegant and easy to use except for one minor defect — difficulty of adding footnote. Unlike adding title, it’s no explicit statement available to add a footnote directly. Let’s use the following plot as example (according to the mpg data set included in ggplot2).

toyota <- mpg[which(mpg$manufacturer == 'toyota'), ]
p <- ggplot(toyota, aes(displ, hwy)) + facet_wrap(~ class, ncol = 2) + geom_point(aes(size=cyl))


As you can see, I create a 4-panel scatter plot using displ as x-axis and hwy as y-axis. Let’s see how we can add the footnote to the plot.

Option 1. The first idea comes into my mind is the ggplot2 annotate() function.  The annotate function can be used to add any text in the plot. The code will look like this, if we want to add a footnote:

p + annotate("text", label = "Footnote", x = 2.5, y = 10, size = 5, colour = "black"))


This successfully adds the footnote, however it has the following problems:

  • It is repeated 4 times, in each of the 4 facets, rather than only one footnote.
  • It is contained within the plots, rather than external to them.
  • The position of text need to be manually adjusted.


Option 2. In order to fix these problems, we introduce the grid.txt() function. Since ggplot2 is based on grid, grid.txt() can add a txt external to the plot and the nice thing is that you can produce multiple graphics and still the footnote will be positioned correctly.

# write a simple function to add footnote
makeFootnote <- function(footnoteText =
                         format(Sys.time(), "%d %b %Y"),
                         size = .7, color = grey(.5))
  grid.text(label = footnoteText ,
    x = unit(1,"npc") - unit(2, "mm"),
    y = unit(2, "mm"),
    just = c("right", "bottom"),
    gp = gpar(cex = size, col = color))
# open an appropriate graphics device
png("/Users/Alan/Desktop/plot_grid_txt.png", width = 641, height = 343)
# call makeFootnote function to add footnote
makeFootnote("Footnote", color = "black")


Although this method puts the footnote in the correct position on the x11() display, it still faces a small problem. I know someone prefer to using the ggsave() instead of this png() … code … style when creating plot in R. Unfortunately, the grid.txt() method cannot be used with ggsave() because the footnote isn’t applied to the object p and therefore cannot be saved by the ggsave().


Option 3. To solve this problem, we need the arrangeGrob() function in gridExtra.

g <- arrangeGrob(p, sub = textGrob("Footnote", x = 0, hjust = -0.1, vjust=0.1, gp = gpar(fontface = "italic", fontsize = 18)))
ggsave("/Users/Alan/Desktop/plot_grid_extra.png", g)



Update (06/2016)

As Tom and Tine mentioned below, the sub = option has been deprecated under gridExtra 2.0 and the resulting figure will be rescaled (i.e. footnote will take the whole bottom half of page). The solution is really simple: switch to bottom = option instead.

footnote <- "Footnote1\nFootnote2"
g <- arrangeGrob(p, bottom = textGrob(footnote, x = 0, hjust = -0.1, vjust=0.1, gp = gpar(fontface = "italic", fontsize = 12)))










Posted in Data Visualization and tagged .


  1. Hi Alan, thanks for the great post!
    I have a quick question: how can I add multiple-line footnote using the `arrangeGrob` method? I tried to use “\n” in the footnote text, but it doesn’t work well. Thanks!

  2. (3) seems to have broken under gridExtra 2.0.0, which has deprecated the sub = argument and now returns a TableGrob instead of a ggplot2-compatible object. It looks like (2) is the more robust solution.

  3. The code above worked like a charm for me:

    toyota <- mpg[which(mpg$manufacturer == 'toyota'), ]
    p <- ggplot(toyota, aes(displ, hwy)) + facet_wrap(~ class, ncol = 2) + geom_point(aes(size=cyl))
    g <- arrangeGrob(p, sub = textGrob("Footnote", x = 0, hjust = -0.1, vjust=0.1, gp = gpar(fontface = "italic", fontsize = 18)))
    ggsave("/Users/tinecasneuf/Desktop/plot_grid_extra.png", g)

    Since some updates, the figure is rescaled, unfortunately. Any thoughts on why this is?

    Thanks a lot!

    My sessionInfo():

    R version 3.1.2 (2014-10-31)
    Platform: x86_64-apple-darwin13.4.0 (64-bit)

    [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

    attached base packages:
    [1] grid stats graphics grDevices utils datasets methods base

    other attached packages:
    [1] gridExtra_2.0.0 ggplot2_1.0.1.9003

    loaded via a namespace (and not attached):
    [1] colorspace_1.2-6 digest_0.6.8 gtable_0.1.2 labeling_0.3 munsell_0.4.2 plyr_1.8.3 Rcpp_0.12.0 scales_0.3.0 tools_3.1.2

  4. Thank you! … I found the third version using arrangeGrob particularly helpful. One problem however seems to be, that it cannot be automatically centered below the plot. I had to try and shift the footnote manually – so there is no guarantee that I ended up with the actual center.

    Do you have any hints for the positioning of the footnote?

Leave a Reply

Your email address will not be published. Required fields are marked *