简体   繁体   English

R:如何将全局/跨 X 轴和 Y 轴添加到拼凑而成的 ggplot 图网格?

[英]R: How can I add global/spanning X and Y axes to a grid of ggplot plots with patchwork?

I am trying to create a global/spanning Y-axis title and a global/spanning X-axis title for a plot containing several ggplot objects arranged in a grid with clockwork .我正在尝试为 plot 创建一个全局/跨越 Y 轴标题一个全局/跨越 X 轴标题,其中包含几个ggplot对象,这些对象排列在一个带有clockwork的网格中。 A global axis title is one that replaces the multiple axis titles along some margin of the plot with a single title, a shown in Step 2 to Step 4 below.全局轴标题是用单个标题替换 plot 的某些边缘的多个轴标题,如下面的步骤 2 至步骤 4 所示。 Although this post shows how to create a global Y axis title, it does not show how to create do so for both the X and Y axes.虽然这篇文章展示了如何创建一个全局 Y 轴标题,但它没有展示如何为 X 轴和 Y 轴创建这样标题。

My issue is that my attempt at creating a global X-axis title places it far away from the other plots and shifts the Y-axis title so it is not centered in the plot.我的问题是,我尝试创建全局 X 轴标题使其远离其他绘图并移动 Y 轴标题,因此它不在 plot 的中心。 In the following reproducible examples, I show my starting point, successful creation of one global axis, and then (starting at Step 3) my failed attempts to add more alongside what I expected to produce.在以下可重现的示例中,我展示了我的起点,成功创建了一个全局轴,然后(从第 3 步开始)我失败的尝试添加更多内容以及我期望生成的内容。 Does anyone know how I can add the global x-axes close to the rest of the plot without shifting the y-axis substantially toward the top of the figure?有谁知道如何在不将 y 轴大幅移向图顶部的情况下,如何在 plot 的 rest 附近添加全局 x 轴?

1. X and Y axis titles for each cell 1. 每个单元格的 X 和 Y 轴标题

This is my "starting" plot: it has a 2x2 layout with axis titles for each cell.这是我的“开始” plot:它有一个 2x2 布局,每个单元格都有轴标题。 I'll want to replace these with fewer axis titles.我想用更少的轴标题替换这些。

library(ggplot2)
library(patchwork)

# Create a list of 4 plots, then render
plot_list <- rep(list(ggplot(mtcars, aes(mpg, disp)) +geom_point()), 4)
wrap_plots(plot_list, nrow = 2)

2. Add a global Y-axis title 2.添加全局Y轴标题

The cell-specific Y-axis titles are successfully replaced with a single, global Y-axis title.单元格特定的 Y 轴标题已成功替换为单个全局 Y 轴标题。 However, each cell still has its own X-axis title.但是,每个单元格仍然有自己的 X 轴标题。

# Same list of 4 plots
plot_list <- rep(list(ggplot(mtcars, aes(mpg, disp)) +geom_point()), 4)

# Loop through list to remove each plot's Y-axis
for(i in 1:length(plot_list)){
  plot_list[[i]] <- plot_list[[i]] + theme(axis.title.y = element_blank())
}

# Create geom_text figure with Y-axis title that will fill the first column
y_lab_big <- ggplot() + 
  annotate(geom = "text", x = 1, y = 1, 
           label = "Here is some example long Y-axis text.", angle = 90) +
  coord_cartesian(clip = "off")+
  theme_void()

# Specify the text plot is NOT stacked and is much less wide
(y_lab_big | wrap_plots(plot_list, nrow = 2)) +
  plot_layout(widths = c(.1, 1))

3. Try to add a global X-axis title 3.尝试添加全局X轴标题

I successfully replace each cell's x-axis title with a single, global x-axis title.我成功地将每个单元格的 x 轴标题替换为单个全局 x 轴标题。 However, it is far from the 2x2 grid and the y-axis title is now not centered on the 2x2 grid.但是,它远离 2x2 网格,并且 y 轴标题现在不在 2x2 网格上居中。

plot_list <- rep(list(ggplot(mtcars, aes(mpg, disp)) + geom_point()), 4)

# Loop through list to remove BOTH X-axis and Y-axis from every plot
for(i in 1:length(plot_list)){
  plot_list[[i]] <- plot_list[[i]] + theme(axis.title.y = element_blank(),
                                 axis.title.x = element_blank())
}

# Create geom_text figures for *Y-axis* title (just like Example 2)
y_lab_big <- 
  ggplot() + 
  annotate(geom = "text", x = 1, y = 1, label = "Here is some example long Y-axis text.", angle = 90) +
  coord_cartesian(clip = "off")+
  theme_void()

# Create geom_text figures for *X-axis* title (different angle)
x_lab_big <- 
  ggplot() + 
  annotate(geom = "text", x = 1, y = 1, label = "Big X Text", angle = 0) +
  coord_cartesian(clip = "off")+
  theme_void()

# Same as Step 2 but add x-axis title using / to indicate that it should
# be stacked below the plot_list plots and specify heights to the thirst row
# (which should be the x-axis title) is relatively small.
(y_lab_big | (wrap_plots(plot_list, nrow = 2)) / x_lab_big) +
  plot_layout(widths = c(.1, 1),
              heights = c(1,1,.1))

Ideally looks like below, with y_title centered between [1.1] and [2,1] and x_title centered between [3,2] [3,3].理想情况下如下所示,y_title 位于 [1.1] 和 [2,1] 之间,x_title 位于 [3,2] [3,3] 之间。

matrix(c("y_title", "y_title", NA,
         "scatter1","scatter2", "x_title",
         "scatter3","scatter4","x_title"), nrow = 3, ncol = 3)
#>      [,1]      [,2]       [,3]      
#> [1,] "y_title" "scatter1" "scatter3"
#> [2,] "y_title" "scatter2" "scatter4"
#> [3,] NA        "x_title"  "x_title"

4. Adding more than one global X-axis title 4.添加多个全局X轴标题

Here I attempt to add a second global X-axis title so that each column receives its own x-axis title but all rows share the same axis title.在这里,我尝试添加第二个全局 X 轴标题,以便每接收自己的 X 轴标题,但所有行共享相同的轴标题。 The issue remains the same.问题仍然相同。

plot_list <- rep(list(ggplot(mtcars, aes(mpg, disp)) + geom_point()), 4)

# Loop through list to remove BOTH X-axis and Y-axis from every plot
for(i in 1:length(plot_list)){
  plot_list[[i]] <- plot_list[[i]] + theme(axis.title.y = element_blank(),
                                           axis.title.x = element_blank())
}

# Create geom_text figures for *Y-axis* title (just like Example 2)
y_lab_big <-  ggplot() + 
  annotate(geom = "text", x = 1, y = 1, label = "Here is some example long Y-axis text.", angle = 90) +
  coord_cartesian(clip = "off")+
  theme_void()

# Create geom_text figures for *X-axis* title (different angle)
x_lab_big <- ggplot() + 
  annotate(geom = "text", x = 1, y = 1, label = "X Text 1", angle = 0) +
  coord_cartesian(clip = "off")+
  theme_void()

x_lab_big2 <- ggplot() + 
  annotate(geom = "text", x = 1, y = 1, label = "X Text 2", angle = 0) +
  coord_cartesian(clip = "off")+
  theme_void()

# Same as previous but add x-axis title using / to indicate that it should
# be stacked below the plot_list plots and specify heights to the thirst row
# (which should be the x-axis title) is relatively small.
(y_lab_big | (wrap_plots(plot_list, nrow = 2)) / (x_lab_big | x_lab_big2)) +
  plot_layout(widths = c(.1, 1),
              heights = c(1, .1))

Ideally looks like below, with y_title centered between [1,1] and [2,1], x_title1 centered in [3,2], and x_title3 centered in [3,3].理想情况下如下所示,y_title 在 [1,1] 和 [2,1] 之间居中,x_title1 在 [3,2] 中居中,x_title3 在 [3,3] 中居中。

matrix(c("y_title", "y_title", NA,
         "scatter1","scatter2", "x_title1",
         "scatter3","scatter4","x_title2"), nrow = 3, ncol = 3)
#>      [,1]      [,2]       [,3]      
#> [1,] "y_title" "scatter1" "scatter3"
#> [2,] "y_title" "scatter2" "scatter4"
#> [3,] NA        "x_title1" "x_title2"

Although there are alternative solutions ( ggplot: how to add common x and y labels to a grid of plots ) I am trying to stay with using patchwork .虽然有替代解决方案( ggplot:如何将常见的 x 和 y 标签添加到绘图网格),但我试图继续使用patchwork

Hopefully patchwork will gain this feature in one of the next releases.希望patchwork将在下一个版本中获得此功能。 In the meanwhile one option would be to stick with patchwork and get some support from cowplot .同时,一种选择是坚持patchwork并从cowplot获得一些支持。 Adapting my answer on R ggplot2 patchwork common axis labels to your case(s):根据您的案例调整我对R ggplot2 拼凑公共轴标签的回答:

Note: That works nice if there is no legend.注意:如果没有图例,那效果很好。 With a legend it gets probably more fiddling.有了一个传说,它可能会变得更加摆弄。

library(ggplot2)
library(patchwork)
library(cowplot)

p <- ggplot(mtcars, aes(mpg, disp)) +
  geom_point()
plot_list <- rep(list(p + labs(x = NULL, y = NULL)), 4)

p_axis <- p + labs(x = "Big X Text", y = "Here is some example long Y-axis text.")
x_axis <- cowplot::get_plot_component(p_axis, "xlab-b")
y_axis <- cowplot::get_plot_component(p_axis, "ylab-l")

design = "
FAB
FCD
#EE
"

c(plot_list, list(x_axis, y_axis)) |> 
  wrap_plots() + 
  plot_layout(heights = c(20, 20, 1), widths = c(1, 25, 25), design = design)

And for the eg two separate x titles you could do:对于例如两个单独的 x 标题,您可以执行以下操作:

Note: For that case another option would be to remove the axis titles for only the top two plots.注意:对于这种情况,另一种选择是仅删除前两个图的轴标题。


p_axis1 <- p + labs(x = "X Text 1", y = "Here is some example long Y-axis text.")
p_axis2 <- p + labs(x = "X Text 2", y = "Here is some example long Y-axis text.")
x_axis1 <- cowplot::get_plot_component(p_axis1, "xlab-b")
x_axis2 <- cowplot::get_plot_component(p_axis2, "xlab-b")

design = "
GAB
GCD
#EF
"


c(plot_list, list(x_axis1, x_axis2, y_axis)) |> 
  wrap_plots() + 
  plot_layout(heights = c(20, 20, 1), widths = c(1, 25, 25), design = design)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM