Reputation: 2293
I use patchwork to assemble plots made with ggplot2. I also use patchwork's plot_annotation()
command to automatically annotate the assembled plots—for example, to automatically place "A", "B", etc. in the upper right-hand corner of each plot. For the most part, this is easy to do. But when the plots have axis labels in different positions, it is hard to get the annotations in the right positions. Here is a minimal illustration of the problem:
library(ggplot2)
library(patchwork)
pLeft <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
scale_y_continuous("Left-hand panel", position = "left")
pRight <- pLeft +
scale_y_continuous("Right-hand panel", position = "right")
pLeft + pRight +
plot_layout(nrow = 1) &
plot_annotation(tag_levels = "A") &
theme(plot.tag.position = c(.935, .96))
That code produces a two-panel figure. The tag for the first panel, "A", is in the correct position. But the tag for the second panel, "B", is not:
There are several ways to fix the problem. For example, I can specify plot.tag.position
separately for each panel:
pLeft + theme(plot.tag.position = c(.935, .96)) +
pRight + theme(plot.tag.position = c(.785, .96)) +
plot_layout(nrow = 1) &
plot_annotation(tag_levels = "A")
Or I can skip plot_annotation()
entirely and just use annotation_custom()
for each panel. But these are bad solutions. The problem is that they require specifying the tag coordinates separately for each panel. And I will sometimes have many panels in the assembled figure—say, N × 2 panels in a two-column figure. In this case, I would like to specify the coordinates only twice: once for the left-hand column, and once for the right-hand column. Is this possible?
I've looked to the patchwork website and here on Stack Overflow for relevant posts, but I haven't found any solutions.
Upvotes: 4
Views: 6454
Reputation: 2293
There are at least four patchwork-based ways to solve the problem: three ways to specify the tag coordinates only once for each column, even if the figure has a large number of panels. (Thomas Lin Pedersen’s excellent patchwork vignettes helped me to find these solutions.) Below, I illustrate the four approaches. They all create this figure:
library(ggplot2)
library(patchwork)
pLeft <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
scale_y_continuous("Left-hand panel", position = "left")
pRight <- pLeft +
scale_y_continuous("Right-hand panel", position = "right")
When using patchwork, x / y
means "stack ggplot object x
on top of ggplot object y
."
((pLeft / pLeft) &
theme(plot.tag.position = c(.935, .96))) -
((pRight / pRight) &
theme(plot.tag.position = c(.785, .96))) +
plot_annotation(tag_levels = "A")
leftCol <- (pLeft / pLeft) & theme(plot.tag.position = c(.935, .96))
rightCol <- (pRight / pRight) & theme(plot.tag.position = c(.785, .96))
wrap_plots(leftCol, rightCol) & # or "leftCol - rightCol"
plot_annotation(tag_levels = "A")
myPlot <- pLeft + pRight + pLeft + pRight +
plot_layout(nrow = 2) &
theme(plot.tag.position = c(.935, .96)) &
plot_annotation(tag_levels = "A")
for (i in c(2, 4)) myPlot[[i]] <- myPlot[[i]] + theme(plot.tag.position = c(.785, .96))
myPlot
This approach relies on Paul Murrell's relatively new ggrid package. Its advantage, relative to the other approaches, is that it permits you to specify only one pair of tag coordinates, no matter how many columns or rows you have in your figure.
library(gggrid) # devtools::install_github("pmur002/gggrid")
myPlot <- pLeft + pRight + pLeft + pRight +
plot_layout(nrow = 2)
for (i in 1:(length(myPlot$patches$plots) + 1)) {
myTag <- textGrob(LETTERS[i], x = .925, y = .95)
myPlot[[i]] <- myPlot[[i]] + grid_panel(myTag)
}
myPlot
Upvotes: 6
Reputation: 23598
A workaround could be creating 2 themes and adding the left theme to the plots on the left and the right theme to the plots on the right.
library(ggplot2)
library(patchwork)
theme_left <- function(...) {
theme_gray(...) %+replace%
theme(
plot.tag.position = c(.935, .96)
)
}
theme_right <- function(...) {
theme_gray(...) %+replace%
theme(
plot.tag.position = c(.785, .96)
)
}
pLeft <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
scale_y_continuous("Left-hand panel", position = "left") +
theme_left()
pRight <- pLeft +
scale_y_continuous("Right-hand panel", position = "right") +
theme_right()
pLeft + pRight +
plot_layout(nrow = 1) &
plot_annotation(tag_levels = "A")
Upvotes: 1