You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ggplot2+patchwork组合多图:跨patchworkGrob背景透明失效问题

解决多面板ggplot图形跨patchworkGrob时的透明背景失效问题

问题描述

制作多面板图形时,为节省空间需要重叠部分面板,已在theme()中设置plot.background和panel.background为透明,但当重叠的绘图分属不同patchworkGrob时,透明效果失效——比如示例中面板D的不透明背景会遮挡面板B的Y轴文本。

示例代码

library(ggplot2)
library(gridExtra)
library(patchwork)
library(ggpubr)

d1 <- data.frame(
  val1=rnorm(500,1,1),
  val2=rnorm(500,1,2),
  val3=rnorm(500,1,3)
)

pA <- ggplot(d1) + 
  geom_density(aes(x=val1)) +
  theme(aspect.ratio = 1,
        plot.background = element_rect(fill = "transparent", color="#808080"))


pC <- ggplot(d1) + 
  geom_density(aes(x=val2)) +
  theme_pubr() +
  theme(        
        plot.background = element_rect(fill = "transparent", color="#808080"))

pD <- ggplot(d1) + 
  geom_density(aes(x=val3)) +
  theme_pubr() +
  theme(
        plot.background = element_rect(fill = "transparent", color="#808080"),
        panel.background = element_rect(fill = "transparent", color="#808080")
        )

df_mtcars <- as.data.frame(mtcars)
df_mtcars$name <- rownames(df_mtcars)
df_mtcars$cyl <- as.factor(df_mtcars$cyl)

pB <- ggplot(df_mtcars) +
  geom_col(aes(x=hp, y=name, fill=cyl)) +
  theme_minimal() +
  scale_x_continuous(position="top") +
  scale_y_discrete(limits=rev) +
  theme(legend.position = "bottom",
        plot.background = element_rect(fill = "transparent", color="#808080")) +
  labs(y=NULL, x="HP") +
  guides(fill=guide_legend(
    title.position="top",
    byrow=TRUE, 
    nrow=3
  ))



grid.arrange(
  patchworkGrob(pA + plot_layout(widths=1) +
      plot_annotation(tag_levels = list(c('A')) ) &
        theme(plot.tag = element_text(size = 15, face = "bold"))
  ),
  patchworkGrob(pB + 
                  plot_annotation(tag_levels = list(c('B')) ) & 
                  theme(plot.tag = element_text(size = 15, face = "bold")) 
  ),
  patchworkGrob(
     pC + 
          plot_spacer()  +
     pD + 
       plot_spacer() +
       plot_layout(widths = c(1, 
                              0.01,
                              1, -0.65)) + 
       plot_annotation(tag_levels = list(c('C', 'D')) ) & 
          theme(plot.tag = element_text(size = 15, face = "bold"))
  ),
  widths=c(1, 0.75),
  heights=c(1, 0.65),
  layout_matrix=rbind(c(1,2),c(3,2))
    )

解决方案

问题根源在于每个patchworkGrob会生成一个顶层容器grob,默认带有不透明白色背景,即使子图设置了透明,这个顶层背景依然会遮挡下方图形。以下两种方法可解决该问题:

方法1:手动修改patchworkGrob的顶层背景为透明

通过grid包工具定位并修改每个patchworkGrob的顶层背景元素,将其填充色设为透明:

# 先定义所有patchworkGrob对象
gA <- patchworkGrob(pA + plot_layout(widths=1) +
                      plot_annotation(tag_levels = list(c('A')) ) &
                      theme(plot.tag = element_text(size = 15, face = "bold")))
gB <- patchworkGrob(pB + 
                      plot_annotation(tag_levels = list(c('B')) ) & 
                      theme(plot.tag = element_text(size = 15, face = "bold")))
gCD <- patchworkGrob(
  pC + 
    plot_spacer()  +
    pD + 
    plot_spacer() +
    plot_layout(widths = c(1, 
                           0.01,
                           1, -0.65)) + 
    plot_annotation(tag_levels = list(c('C', 'D')) ) & 
    theme(plot.tag = element_text(size = 15, face = "bold"))
)

# 定义修改grob背景的函数
modify_grob_background <- function(grob_obj) {
  bg_idx <- which(sapply(grob_obj$children, function(x) inherits(x, "rect")))
  for (idx in bg_idx) {
    grob_obj$children[[idx]]$gp$fill <- "transparent"
  }
  return(grob_obj)
}

# 应用修改
gA <- modify_grob_background(gA)
gB <- modify_grob_background(gB)
gCD <- modify_grob_background(gCD)

# 重新组合布局
grid.arrange(
  gA,
  gB,
  gCD,
  widths=c(1, 0.75),
  heights=c(1, 0.65),
  layout_matrix=rbind(c(1,2),c(3,2))
)

方法2:使用patchwork原生inset_element实现重叠布局

如果场景允许,直接用patchwork的inset_element功能嵌入需要重叠的子图,避免拆分多个patchworkGrob:

# 构建主布局
main_layout <- pA + pB + 
  plot_layout(widths = c(1, 0.75), heights = c(1)) +
  plot_annotation(tag_levels = c('A', 'B')) &
  theme(plot.tag = element_text(size = 15, face = "bold"))

# 插入CD组合图到指定位置
final_plot <- main_layout +
  inset_element(
    pC + pD + plot_layout(widths = c(1, 0.01, 1, -0.65)) +
      plot_annotation(tag_levels = list(c('C', 'D'))) &
      theme(plot.tag = element_text(size = 15, face = "bold")),
    left = 0, bottom = 0, right = 1, top = 0.65, # 匹配原布局位置
    on_top = FALSE # 根据需求设置图层顺序
  )

# 输出图形
final_plot

说明

  • 方法1适合保留原有grid.arrange布局逻辑的场景,直接修改grob属性,兼容性强。
  • 方法2更贴合patchwork原生布局逻辑,减少多grob组合的兼容性问题,推荐优先尝试。

内容的提问来源于stack exchange,提问作者dkysh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 04:13:11