如何在包含一组 ggplot2 散点图的 gridExtra 中通过 arrange.grid 创建的图表周围添加边框

How to add a border around a chart created via arrange.grid in gridExtra encompassing a set ggplot2 scatter plots

我正在使用以下代码:

# Libs
require(ggplot2); require(gridExtra); require(grid)

# Generate separate charts
chrts_list_scts <- list()

# Data
data("mtcars")

# A
chrts_list_scts$a <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = disp,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = disp),
              method = "auto") +
  xlab("MPG") +
  ylab("Disp") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

# B
chrts_list_scts$b <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = drat,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = drat),
              method = "auto") +
  xlab("MPG") +
  ylab("Drat") +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

# C
chrts_list_scts$c <- ggplot(mtcars) +
  geom_point(size = 2, aes(x = mpg, y = qsec,
                           colour = as.factor(cyl))) +
  geom_smooth(aes(x = mpg, y = qsec),
              method = "auto") +
  xlab("MPG") +
  ylab("QSEC") +
  guides(colour = guide_legend(title = "cyl")) +
  theme_bw() +
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "bottom",
        legend.key = element_rect(colour = NA))

# Arrange grid
png(filename = "chrts.PNG", width = 6,
    height = 10, units = 'in', res = 300)
title_text <- c("mtcars")
chrts_list_scts$all_scts <- grid.arrange(chrts_list_scts$a,
                                         chrts_list_scts$b,
                                         chrts_list_scts$c,
                                         top =
                                           textGrob(label = title_text,
                                                    gp = gpar(
                                                      fontsize = 14,
                                                      font = 2)))
dev.off()
rm(title_text)

生成如下图表:

我有兴趣在该图表周围添加边框, 如下图所示:

尝试次数

我试图通过在代码中添加 polygonGrob 来解决此请求:

chrts_list_scts$all_scts <- grid.arrange(chrts_list_scts$dep_work,
                                         chrts_list_scts$chld_work,
                                         chrts_list_scts$pens,
                                         polygonGrob(x = c(0,0.5,1.05),
                                                     y = c(0,0.5,1.05)
                                                     ),
                                         top =
                                           textGrob(label = title_text,
                                                    gp = gpar(
                                                      fontsize = 14,
                                                      font = 2)))

但这会生成一个毫无意义的图表,底部有一条横线。我看过看似相似的 discussion on SO,但我不清楚如何找到有效的解决方案。

侧面要求

除了生成边框,我还想:

  1. 能够对边框美学进行一些控制,例如更改边框的大小和颜色。
  2. 理想情况下,我想将此解决方案 封装在 arrange.grid 调用中。所以对象 chrts_list_scts$all_scts 包含所有元素,包括图表和所有元素周围的整齐边框。

我很乐意接受仅解决边界方面主要要求的解决方案,如果有建议的解决方案与其余两点相匹配,那就更好了。

1) 使用问题中提供的 link 中的 iris 示例(但进一步简化)只需添加最后一行。修改 gpar(...) 组件(可能还有 widthheight)以获得不同的美感。 (这未封装在 grid.arrange 调用中。)

library(ggplot2)
library(grid)
library(gridExtra)

g <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) + geom_point()
grid.arrange(g, g, ncol=2)


# next line adds border
grid.rect(width = .98, height = .98, gp = gpar(lwd = 2, col = "blue", fill = NA))

(剧情后续)

2) 这是解决方案 (1) 的一个变体,其中在正面通过创建 grobs 将图形和边框封装在 gt gTree 中握住每一个。另一方面,它确实涉及一些额外的复杂性:

grid.newpage()
ga <- arrangeGrob(g, g, ncol = 2)
gb <- rectGrob(height = .98, width = .98, gp = gpar(lwd = 2, col = "blue", fill = NA)) # border, no fill
gt <- gTree(children = gList(ga, gb))
grid.draw(gt)

你可以添加一个rectGrob到gtable

grid.draw(gtable::gtable_add_grob(arrangeGrob(g, g, ncol=2),
             rectGrob(gp=gpar(lwd=5, fill=NA)), 1, 1, 1, 2))

注意:fill=NAfill='transparent' 是必需的,否则矩形会掩盖其下方的对象。