Skip to content

Commit

Permalink
Canonicalize markdown (#364)
Browse files Browse the repository at this point in the history
Fixes #361
  • Loading branch information
hadley committed May 1, 2023
1 parent 59ff1b6 commit 3e6b51e
Show file tree
Hide file tree
Showing 26 changed files with 3,224 additions and 1,813 deletions.
278 changes: 151 additions & 127 deletions annotations.Rmd

Large diffs are not rendered by default.

74 changes: 56 additions & 18 deletions arranging-plots.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@ source("common.R")
columns(1, 1 / 1.61, 1)
```

The grammar presented in ggplot2 is concerned with creating single plots. While the faceting system provides the means to produce several subplots all of these are part of the same main visualization, sharing layers, data, and scales. However, it is often necessary to use multiple disparate plots to tell a story or make an argument. These can of course be created individually and assembled in a layout program, but it is beneficial to do this in code to avoid time consuming and non-reproducible manual labor. A range of packages have risen to the occasion and provide different approaches to arranging separate plots. While this chapter will focus on the patchwork package you may also find some of the same functionalities in the cowplot, gridExtra and ggpubr packages.
The grammar presented in ggplot2 is concerned with creating single plots.
While the faceting system provides the means to produce several subplots all of these are part of the same main visualization, sharing layers, data, and scales.
However, it is often necessary to use multiple disparate plots to tell a story or make an argument.
These can of course be created individually and assembled in a layout program, but it is beneficial to do this in code to avoid time consuming and non-reproducible manual labor.
A range of packages have risen to the occasion and provide different approaches to arranging separate plots.
While this chapter will focus on the patchwork package you may also find some of the same functionalities in the cowplot, gridExtra and ggpubr packages.

This chapter will be split into two parts. The first will be concerned with arranging plots side by side with no overlap, while the second will be concerned with arranging plots on top of each other. While these two scenarios are not necessarily in opposition to each other, the former scenario will often benefit from functionality that makes little sense in the latter, e.g. alignment of plotting regions.
This chapter will be split into two parts.
The first will be concerned with arranging plots side by side with no overlap, while the second will be concerned with arranging plots on top of each other.
While these two scenarios are not necessarily in opposition to each other, the former scenario will often benefit from functionality that makes little sense in the latter, e.g. alignment of plotting regions.

## Laying out plots side by side

Often, one wants to show two or more plots side by side to show different aspects of the same story in a compelling way. This is the scenario that patchwork was build to solve. At its heart, patchwork is a package that extends ggplot2's use of the `+` operator to work between multiple plots, as well as add additional operators for specialized compositions and working with compositions of plots.
Often, one wants to show two or more plots side by side to show different aspects of the same story in a compelling way.
This is the scenario that patchwork was build to solve.
At its heart, patchwork is a package that extends ggplot2's use of the `+` operator to work between multiple plots, as well as add additional operators for specialized compositions and working with compositions of plots.

As an example of the most basic use of patchwork, we'll use the following 4 plots of the `mpg` dataset

Expand Down Expand Up @@ -40,23 +49,29 @@ library(patchwork)
p1 + p2
```

`+` does not specify any specific layout, only that the plots should be displayed together. In the absence of a layout the same algorithm that governs the number of rows and columns in `facet_wrap()` will decide the number of rows and columns. This means that adding 3 plots together will create a 1x3 grid while adding 4 plots together will create a 2x2 grid.
`+` does not specify any specific layout, only that the plots should be displayed together.
In the absence of a layout the same algorithm that governs the number of rows and columns in `facet_wrap()` will decide the number of rows and columns.
This means that adding 3 plots together will create a 1x3 grid while adding 4 plots together will create a 2x2 grid.

```{r}
p1 + p2 + p3 + p4
```

As can be seen from the two examples above, patchwork takes care of aligning the different parts of the plots with each other. You can see that all plotting regions are aligned, even in the presence of faceting. Further, you can see that the y-axis titles in the two left-most plots are aligned despite the axis text in the bottom left plot being wider.
As can be seen from the two examples above, patchwork takes care of aligning the different parts of the plots with each other.
You can see that all plotting regions are aligned, even in the presence of faceting.
Further, you can see that the y-axis titles in the two left-most plots are aligned despite the axis text in the bottom left plot being wider.

### Taking control of the layout

It is often that the automatically created grid is not what you want and it is of course possible to control it. The most direct and powerful way is to do this is to add a `plot_layout()` specification to the plot:
It is often that the automatically created grid is not what you want and it is of course possible to control it.
The most direct and powerful way is to do this is to add a `plot_layout()` specification to the plot:

```{r}
p1 + p2 + p3 + plot_layout(ncol = 2)
```

A common scenario is wanting to force a single row or column. patchwork provides two operators, `|` and `/` respectively, to facilitate this (under the hood they simply set number of rows or columns in the layout to 1).
A common scenario is wanting to force a single row or column.
patchwork provides two operators, `|` and `/` respectively, to facilitate this (under the hood they simply set number of rows or columns in the layout to 1).

```{r}
p1 / p2
Expand Down Expand Up @@ -85,29 +100,37 @@ CDD
p1 + p2 + p3 + p4 + plot_layout(design = layout)
```

As has been apparent in the last couple of plots the legend often becomes redundant between plots. While it is possible to remove the legend in all but one plot before assembling them, patchwork provides something easier for the common case:
As has been apparent in the last couple of plots the legend often becomes redundant between plots.
While it is possible to remove the legend in all but one plot before assembling them, patchwork provides something easier for the common case:

```{r}
p1 + p2 + p3 + plot_layout(ncol = 2, guides = "collect")
```

Electing to collect guides will take all guides and put them together at the position governed by the global theme. Further, it will remove any duplicate guide leaving only unique guides in the plot. The duplication detection looks at the appearance of the guide, and not the underlying scale it comes from. Thus, it will only remove guides that are exactly alike. If you want to optimize space use by putting guides in an empty area of the layout, you can specify a plotting area for collected guides:
Electing to collect guides will take all guides and put them together at the position governed by the global theme.
Further, it will remove any duplicate guide leaving only unique guides in the plot.
The duplication detection looks at the appearance of the guide, and not the underlying scale it comes from.
Thus, it will only remove guides that are exactly alike.
If you want to optimize space use by putting guides in an empty area of the layout, you can specify a plotting area for collected guides:

```{r}
p1 + p2 + p3 + guide_area() + plot_layout(ncol = 2, guides = "collect")
```

### Modifying subplots

One of the tenets of patchwork is that the plots remain as standard ggplot objects until rendered. This means that they are amenable to modification after they have been assembled. The specific plots can by retrieved and set with `[[]]` indexing:
One of the tenets of patchwork is that the plots remain as standard ggplot objects until rendered.
This means that they are amenable to modification after they have been assembled.
The specific plots can by retrieved and set with `[[]]` indexing:

```{r}
p12 <- p1 + p2
p12[[2]] <- p12[[2]] + theme_light()
p12
```

Often though, it is necessary to modify all subplots at once to e.g. give them a common theme. patchwork provides the `&` for this scenario:
Often though, it is necessary to modify all subplots at once to e.g. give them a common theme.
patchwork provides the `&` for this scenario:

```{r}
p1 + p4 & theme_minimal()
Expand All @@ -121,7 +144,9 @@ p1 + p4 & scale_y_continuous(limits = c(0, 45))

### Adding annotation

Once plots have been assembled, they start to form a single unit. This also means that titles, subtitles, and captions will often pertain to the full ensemble and not individual plots. Titles etc. can be added to patchwork plots using the `plot_annotation()` function.
Once plots have been assembled, they start to form a single unit.
This also means that titles, subtitles, and captions will often pertain to the full ensemble and not individual plots.
Titles etc. can be added to patchwork plots using the `plot_annotation()` function.

```{r}
p34 <- p3 + p4 + plot_annotation(
Expand All @@ -143,7 +168,9 @@ As the global theme often follows the theme of the subplots, using `&` along wit
p34 & theme_gray(base_family = "mono")
```

Another type of annotation, known especially in scientific literature, is to add tags to each subplot that will then be used to identify them in the text and caption. ggplot2 has the `tag` element for exactly this and patchwork offers functionality to set this automatically using the `tag_levels` argument. It can generate automatic levels in latin characters, arabic numerals, or roman numerals
Another type of annotation, known especially in scientific literature, is to add tags to each subplot that will then be used to identify them in the text and caption.
ggplot2 has the `tag` element for exactly this and patchwork offers functionality to set this automatically using the `tag_levels` argument.
It can generate automatic levels in latin characters, arabic numerals, or roman numerals

```{r}
p123 <- p1 | (p2 / p3)
Expand All @@ -163,13 +190,18 @@ As can be seen, patchwork offers a long range of possibilities when it comes to

## Arranging plots on top of each other

While a lot of the functionality in patchwork is concerned with aligning plots in a grid, it also allows you to make insets, i.e. small plots placed on top of another plot. The functionality for this is wrapped in the `inset_element()` function which serves to mark the given plot as an inset to be placed on the preceding plot, along with recording the wanted placement etc. The basic usage is like this:
While a lot of the functionality in patchwork is concerned with aligning plots in a grid, it also allows you to make insets, i.e. small plots placed on top of another plot.
The functionality for this is wrapped in the `inset_element()` function which serves to mark the given plot as an inset to be placed on the preceding plot, along with recording the wanted placement etc.
The basic usage is like this:

```{r}
p1 + inset_element(p2, left = 0.5, bottom = 0.4, right = 0.9, top = 0.95)
```

The position is specified by given the left, right, top, and bottom location of the inset. The default is to use `npc` units which goes from 0 to 1 in the given area, but any `grid::unit()` can be used by giving them explicitly. The location is by default set to the panel area, but this can be changed with the `align_to` argument. Combining all this we can place an inset exactly 15 mm from the top right corner like this:
The position is specified by given the left, right, top, and bottom location of the inset.
The default is to use `npc` units which goes from 0 to 1 in the given area, but any `grid::unit()` can be used by giving them explicitly.
The location is by default set to the panel area, but this can be changed with the `align_to` argument.
Combining all this we can place an inset exactly 15 mm from the top right corner like this:

```{r}
p1 +
Expand All @@ -183,14 +215,16 @@ p1 +
)
```

insets are not confined to ggplots. Any graphics supported by `wrap_elements()` can be used, including patchworks:
insets are not confined to ggplots.
Any graphics supported by `wrap_elements()` can be used, including patchworks:

```{r}
p24 <- p2 / p4 + plot_layout(guides = "collect")
p1 + inset_element(p24, left = 0.5, bottom = 0.05, right = 0.95, top = 0.9)
```

A nice feature of insets is that they behave as standard patchwork subplots until they are rendered. This means that they are amenable to modifications after assembly, e.g. using `&`:
A nice feature of insets is that they behave as standard patchwork subplots until they are rendered.
This means that they are amenable to modifications after assembly, e.g. using `&`:

```{r}
p12 <- p1 + inset_element(p2, left = 0.5, bottom = 0.5, right = 0.9, top = 0.95)
Expand All @@ -205,4 +239,8 @@ p12 + plot_annotation(tag_levels = "A")

## Wrapping up

This chapter has given a brief overview of some of the composition possibilities provided by patchwork, but is in no way exhaustive. Patchwork provides support for more than just ggplots and allows you to combine grid and base graphic elements with your plots as well if need be. It also allows even more complex designs using the `area()` constructor instead of the textual representation showcased here. All of these functionalities and many more are covered in the different guides available on its website: <https://patchwork.data-imaginist.com>
This chapter has given a brief overview of some of the composition possibilities provided by patchwork, but is in no way exhaustive.
Patchwork provides support for more than just ggplots and allows you to combine grid and base graphic elements with your plots as well if need be.
It also allows even more complex designs using the `area()` constructor instead of the textual representation showcased here.
All of these functionalities and many more are covered in the different guides available on its website: <https://patchwork.data-imaginist.com>

Loading

0 comments on commit 3e6b51e

Please sign in to comment.