与 cowplot 和 plot_grid 共享面板边框

Posted

技术标签:

【中文标题】与 cowplot 和 plot_grid 共享面板边框【英文标题】:Shared panel border with cowplot and plot_grid 【发布时间】:2016-07-10 03:00:32 【问题描述】:

我正在尝试在与 cowplot 包中的 plot_grid 对齐的两个地块周围绘制边框。请看下面的例子(修改自"Changing the axis positions" vignette):

require(gtable)
require(cowplot)

# top plot
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = 'blue') +
  background_grid(minor = 'none')
g1 <- switch_axis_position(p1, 'xy') # switch both axes
g1 <- gtable_squash_rows(g1, length(g1$height)) # set bottom row to 0 height

# bottom plot
p2 <- ggplot(mtcars, aes(mpg, qsec)) + geom_line(colour = 'green') + ylim(14, 25) +
  background_grid(minor = 'none')
g2 <- ggplotGrob(p2)
g2 <- gtable_add_cols(g2, g1$widths[5:6], 4) # add the two additional columns that g1 has
g2 <- gtable_squash_rows(g2, 1:2) # set top two rows to 0 height

plot_grid(g1, g2, ncol = 1, align = 'v') + 
  annotate("rect", xmin = 0.1, xmax = 0.9, ymin = 0.1, ymax = 0.9, 
           color = "red", fill = NA)

现在,我想让它与轴线对齐,而不是为红色框任意选择坐标。我假设这些坐标可以从plot_grid 输出中提取,但我不知道如何。

【问题讨论】:

【参考方案1】:

根据我对 grobs 的理解,我想说获取每个地块的坐标并添加边界段会更容易使用plot_grid 组合地块之前。

示例数据

library(gtable)
library(cowplot)

# sample plots
# (note: the cowplot function switch_axis_position has been deprecated, as its
# creator notes ggplot2 now natively supports axes on either side of the plot.)
p1 <- ggplot(mtcars, aes(mpg, disp)) + 
  geom_line(colour = 'blue') +
  scale_x_continuous(position = "top") +
  scale_y_continuous(position = "right") +
  background_grid(minor = 'none'); p1

p2 <- ggplot(mtcars, aes(mpg, qsec)) + 
  geom_line(colour = 'green') + 
  ylim(14, 25) +
  background_grid(minor = 'none'); p2

# convert to grob objects
g1 <- ggplotGrob(p1)
g2 <- ggplotGrob(p2)

函数为每个 plot grob 添加适当的边框段,其中:

grob 是通过 ggplotGrob 创建的 grob 对象; sides 是一个字符串,包含"t" / "l" / "b" / "r" 的任意组合,以任意顺序指示边框放置所需的边; col 是所需的边框颜色(默认为红色); ... 用于将任何其他参数传递给segmentsGrob() 中的gpar()

.

library(grid)

add.segments <- function(grob, sides = "tlbr", col = "red", ...)

  # get extent of gtable cells to be surrounded by border
  panel.coords <- g1[["layout"]][g1[["layout"]][["name"]] == "panel", ]
  t <- if(grepl("t", sides)) panel.coords[["t"]] else 1
  b <- if(grepl("b", sides)) panel.coords[["b"]] else length(grob[["heights"]])
  l <- if(grepl("l", sides)) panel.coords[["l"]] else 1
  r <- if(grepl("r", sides)) panel.coords[["r"]] else length(grob[["widths"]])

  # define border coordinates, & filter for the desired border sides
  coords <- data.frame(direction = c("t", "b", "l", "r"),
                       x0 = c(0, 0, 0, 1), y0 = c(1, 0, 0, 0),
                       x1 = c(1, 1, 0, 1), y1 = c(1, 0, 1, 1),
                       stringsAsFactors = FALSE)
  coords <- coords[sapply(coords$direction, grepl, sides), ]

  # add desired border sides as segments to the grob at specific gtable cells
  grob <- gtable_add_grob(x = grob,
                          grobs = segmentsGrob(
                            x0 = coords[["x0"]], y0 = coords[["y0"]],
                            x1 = coords[["x1"]], y1 = coords[["y1"]],
                            gp = gpar(col = col, ...)
                          ),
                          t = t, l = l, b = b, r = r,
                          clip = "off", name = "segments")

  return(grob)

用法

plot_grid(add.segments(g1, "tlr"), 
          add.segments(g2, "lbr"), 
          ncol = 1, align = "v")

另一个例子,水平对齐两个图(好吧,没有必要将这些特定的图并排对齐,但你明白了):

plot_grid(add.segments(g2, "tlb", col = "gold2", lty = 2, lwd = 5), 
          add.segments(g1, "trb", col = "gold2", lty = 2, lwd = 5), 
          nrow = 1, align = "h")

【讨论】:

以上是关于与 cowplot 和 plot_grid 共享面板边框的主要内容,如果未能解决你的问题,请参考以下文章

使用 plot_grid 和 cowplot 删除 NULL 图上的标签

我在 R 中使用 cowplot 和 ggplot2 的 plot_grids 缺少网格中的四个图之一?

如何使用`cowplot`软件包中的`plot_grid`对齐地块最后一列中的图例?

使用cowplot包的多图的居中X轴标签

禁用ggplots的cowplot默认值

如何将普通的ggplot与cowplot中的多面对齐?