使用拼凑来注释在不同位置具有标签的图
using patchwork to annotate plots that have labels in different positions
我使用拼凑 assemble 用 ggplot2 绘制的图。我还使用 patchwork 的 plot_annotation()
命令自动注释 assembled 图——例如,在每个图的右上角自动放置“A”、“B”等。在大多数情况下,这很容易做到。但是当绘图在不同位置有轴标签时,很难在正确的位置获得注释。这是问题的最小说明:
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))
该代码生成一个双面板图形。第一个面板的标签“A”位于正确的位置。但是第二个面板的标签“B”不是:
有多种方法可以解决此问题。例如,我可以为每个面板单独指定 plot.tag.position
:
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")
或者我可以完全跳过 plot_annotation()
,只对每个面板使用 annotation_custom()
。但这些都是糟糕的解决方案。问题是他们需要为每个面板分别指定标签坐标。有时我会在 assembled 图中有很多面板——比如,在两列图中有 N × 2 个面板。在这种情况下,我只想指定两次坐标:一次用于左侧列,一次用于右侧列。这可能吗?
我查看了 patchwork 网站和 Stack Overflow 上的相关帖子,但我没有找到任何解决方案。
解决方法是创建 2 个主题并将左侧主题添加到左侧的绘图,将右侧主题添加到右侧的绘图。
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")
至少有四种基于拼凑的方法来解决这个问题:三种方法为每一列只指定一次标签坐标,即使图中有大量的面板。 (Thomas Lin Pedersen 的出色 patchwork vignettes 帮助我找到了这些解决方案。)下面,我将说明这四种方法。他们都创造了这个数字:
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")
方法 1
使用 patchwork 时,x / y
表示“将 ggplot 对象 x
堆叠在 ggplot 对象 y
之上。”
((pLeft / pLeft) &
theme(plot.tag.position = c(.935, .96))) -
((pRight / pRight) &
theme(plot.tag.position = c(.785, .96))) +
plot_annotation(tag_levels = "A")
方法 2:
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")
方法 3
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
方法 4
此方法依赖于 Paul Murrell 相对较新的 ggrid 包。相对于其他方法,它的优势在于它允许您仅指定一对标记坐标,无论您的图中有多少列或行。
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
我使用拼凑 assemble 用 ggplot2 绘制的图。我还使用 patchwork 的 plot_annotation()
命令自动注释 assembled 图——例如,在每个图的右上角自动放置“A”、“B”等。在大多数情况下,这很容易做到。但是当绘图在不同位置有轴标签时,很难在正确的位置获得注释。这是问题的最小说明:
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))
该代码生成一个双面板图形。第一个面板的标签“A”位于正确的位置。但是第二个面板的标签“B”不是:
有多种方法可以解决此问题。例如,我可以为每个面板单独指定 plot.tag.position
:
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")
或者我可以完全跳过 plot_annotation()
,只对每个面板使用 annotation_custom()
。但这些都是糟糕的解决方案。问题是他们需要为每个面板分别指定标签坐标。有时我会在 assembled 图中有很多面板——比如,在两列图中有 N × 2 个面板。在这种情况下,我只想指定两次坐标:一次用于左侧列,一次用于右侧列。这可能吗?
我查看了 patchwork 网站和 Stack Overflow 上的相关帖子,但我没有找到任何解决方案。
解决方法是创建 2 个主题并将左侧主题添加到左侧的绘图,将右侧主题添加到右侧的绘图。
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")
至少有四种基于拼凑的方法来解决这个问题:三种方法为每一列只指定一次标签坐标,即使图中有大量的面板。 (Thomas Lin Pedersen 的出色 patchwork vignettes 帮助我找到了这些解决方案。)下面,我将说明这四种方法。他们都创造了这个数字:
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")
方法 1
使用 patchwork 时,x / y
表示“将 ggplot 对象 x
堆叠在 ggplot 对象 y
之上。”
((pLeft / pLeft) &
theme(plot.tag.position = c(.935, .96))) -
((pRight / pRight) &
theme(plot.tag.position = c(.785, .96))) +
plot_annotation(tag_levels = "A")
方法 2:
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")
方法 3
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
方法 4
此方法依赖于 Paul Murrell 相对较新的 ggrid 包。相对于其他方法,它的优势在于它允许您仅指定一对标记坐标,无论您的图中有多少列或行。
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