---
title: "Plot annotations"
author: "Claus O. Wilke"
date: "`r Sys.Date()`"
output:
  rmarkdown::html_vignette:
    fig_width: 4
vignette: >
  %\VignetteIndexEntry{Plot annotations}
  %\VignetteEngine{knitr::rmarkdown}
  %\usepackage[utf8]{inputenc}
---
```{r echo=FALSE, message=FALSE}
library(ggplot2)
library(cowplot)
```

The **cowplot** package provides a variety of functions to annotate plots, including annotations underneath the plot, mathematical expressions inside plots, and joint titles for combined plots. Note that as **ggplot2** gains more of this functionality natively (e.g. as of version 2.2.0), we recommend to use the **ggplot2** methods rather than the **cowplot** methods. Any functionality that is duplicated between **ggplot2** and **cowplot** may be removed from future versions of **cowplot**.


## Annotations with mathematical expressions

We commonly want to annotate plots with mathematical expressions, for example when we want to show the result from a statistical test inside the plot. For this purpose, cowplot defines the function `draw_label()`, which can add arbitrary text or mathematical expressions to a plot.

Depending on the application, we may want to specify the location of the label either in absolute coordinates (independently of the data plotted) or in coordinates relative to the data shown. Both uses are supported by `draw_label()`. For the former, we use `draw_label()` in conjunction with `ggdraw()`:
```{r fig.width=5, fig.height=5, warning=FALSE}
p <- ggplot(mtcars, aes(x=disp, y=mpg)) + geom_point(colour = "blue")

c <- cor.test(mtcars$mpg, mtcars$disp, method='sp')
label <- substitute(paste("Spearman ", rho, " = ", estimate, ", P = ", pvalue),
                    list(estimate = signif(c$estimate, 2), pvalue = signif(c$p.value, 2)))
# adding label via ggdraw, in the ggdraw coordinates
ggdraw(p) + draw_label(label, .7, .9)
```

For the latter, we add `draw_label()` directly to the plot:
```{r fig.width=5, fig.height=5}
# adding label directly to plot, in the data coordinates
p + draw_label(label, 200, 32.5, hjust = 0, vjust = 0)
```


## Joint plot titles

When we combine plots with `plot_grid()`, we may want to add a title that spans the entire combined figure. While there is no specific function in **cowplot** to achieve this effect, it can be simulated easily with a few lines of code:
```{r fig.width=8, fig.height=4}
# make a plot grid consisting of two panels
p1 <- ggplot(mtcars, aes(x=disp, y=mpg)) + geom_point(colour = "blue") + background_grid(minor='none')
p2 <- ggplot(mtcars, aes(x=hp, y=mpg)) + geom_point(colour = "green") + background_grid(minor='none')
p <- plot_grid(p1, p2, labels=c('A', 'B'))
# now add the title
title <- ggdraw() + draw_label("MPG declines with displacement and horsepower", fontface='bold')
plot_grid(title, p, ncol=1, rel_heights=c(0.1, 1)) # rel_heights values control title margins
```
In the final `plot_grid` line, the values of `rel_heights` need to be chosen appropriately so that the margins around the title look correct. With the values chosen here, the title takes up 9% (i.e., 0.1/1.1) of the total plot height.

## Annotations underneath plots

The function `add_sub()` can be used to add annotation text underneath a plot. This functionality is now mostly superseded by the `caption` argument to the `labs` function in base **ggplot2**, but `add_sub()` is retained in **cowplot** for backwards compatibility. For new plots, I suggest you try `caption` first and use `add_sub()` only when `caption` doesn't provide the desired result.

To demonstrate how `add_sub()` is used, we first make a plot: 
```{r fig.width=5, fig.height=5}
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue") + background_grid(minor='none')
p1
```

Now we add an annotation underneath:
```{r fig.width=5, fig.height=5}
p2 <- add_sub(p1, "This is an annotation.\nAnnotations can span multiple lines.")
ggdraw(p2)
```

Note that `p2` is not a ggplot object but a gtable. It needs to be drawn with `ggdraw()`.

We can also do this repeatedly, and we can use mathematical expressions instead of plain text.
```{r fig.width=5, fig.height=5}
p2 <- add_sub(p1, "This formula has no relevance here:", y  = 0, vjust = 0)
p3 <- add_sub(p2, expression(paste(a^2+b^2, " = ", c^2)), size=12)
ggdraw(p3)
```

This code also works with faceted plots:
```{r fig.width=7, fig.height=5}
plot.iris <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
  geom_point() + facet_grid(. ~ Species) + stat_smooth(method = "lm") +
  background_grid(major = 'y', minor = "none") + # add thin horizontal lines
  panel_border() # and a border around each panel
p2 <- add_sub(plot.iris, "Annotation underneath a faceted plot, left justified.", x = 0, hjust = 0)
ggdraw(p2)
```

Finally, it is possible to move the annotation inside of the plot if desired. Note that the coordinate `x` is measured relative to the left border of the plot panel but the coordinate `y` is measured relative to the space that has been added underneath the plot. Neither `x` nor `y` are measured in the units of the data plotted. This guarantees that the annotation can be placed in the same location in different plots, regardless of the data shown. 
```{r fig.width=5, fig.height=5}
ggdraw(add_sub(p1, "Annotation inside plot", vpadding=grid::unit(0, "lines"),
       y = 6, x = 0.03, hjust = 0))
```

