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

patchwork中axis_titles='collect'与aspect.ratio兼容问题咨询

关于patchwork中axis_titles='collect'与aspect.ratio兼容问题的解答

核心结论

这是预期设计,而非bug。

原因说明

patchwork会把设置了aspect.ratio=1的图形归类为「固定纵横比图形」,这类图形的尺寸是独立锁定的,不会随布局容器调整。而axis_titles='collect'功能依赖于patchwork统一管理所有子图的轴元素布局,当子图是固定纵横比时,patchwork无法对其轴标题进行全局收集和统一放置——因为每个子图的尺寸是刚性的,无法为了统一轴标题而调整布局空间。

但图例收集(guides='collect')不受影响,因为图例是独立于子图尺寸的全局元素,patchwork可以单独提取并合并放置。

解决方案

方案1:用coord_fixed()替代theme(aspect.ratio=1)

coord_fixed()同样能实现正方形图形,但它是从坐标系统层面锁定比例,不会被patchwork判定为「固定尺寸图形」,因此可以正常使用axis_titles='collect':

library(ggplot2)
library(patchwork)

# 数据集准备
df1 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df1$z <- with(df1, dnorm(x, mean = 500, sd = 50) * dnorm(y, mean = 400, sd = 50))
df2 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df2$z <- with(df2, dnorm(x, mean = 600, sd = 50) * dnorm(y, mean = 450, sd = 50))
df3 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df3$z <- with(df3, dnorm(x, mean = 550, sd = 50) * dnorm(y, mean = 500, sd = 50))
df4 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df4$z <- with(df4, dnorm(x, mean = 650, sd = 50) * dnorm(y, mean = 350, sd = 50))

min_z <- min(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)
max_z <- max(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)

# 用coord_fixed()替代theme(aspect.ratio=1)
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
  ggplot(df, aes(x, y, fill = z)) +
    geom_raster(interpolate = TRUE) +
    theme_minimal() +
    theme(
      legend.position = "bottom",
      legend.box = "horizontal"
    ) +
    coord_fixed(ratio = 1, expand = FALSE)
})

plot_aspr <- wrap_plots(
    p_tmp,
    nrow = 2,
    ncol = 2,
    axis_titles = "collect",
    guides = "collect"
  ) +
  plot_annotation(
    title = "Emission-Excitation-Matrix",
    subtitle = "Rayleigh Filtered Data") &
  labs(
    x = "Emission Wavelength / nm",
    y = "Excitation Wavelength / nm"
  ) &
  scale_fill_viridis_c(limits = c(min_z, max_z))

print(plot_aspr)

方案2:手动隐藏多余轴标题

如果必须使用theme(aspect.ratio=1),可以手动控制每个子图的轴标题显示,只保留最底部的x轴标题和最左侧的y轴标题:

# 生成子图时,根据位置设置轴标题是否显示
p_tmp <- list(
  # 左上:保留y轴标题,隐藏x轴标题
  ggplot(df1, aes(x, y, fill = z)) +
    geom_raster(interpolate = TRUE) +
    theme_minimal() +
    theme(
      aspect.ratio = 1,
      legend.position = "bottom",
      legend.box = "horizontal",
      axis.title.x = element_blank()
    ),
  # 右上:隐藏x、y轴标题
  ggplot(df2, aes(x, y, fill = z)) +
    geom_raster(interpolate = TRUE) +
    theme_minimal() +
    theme(
      aspect.ratio = 1,
      legend.position = "bottom",
      legend.box = "horizontal",
      axis.title.x = element_blank(),
      axis.title.y = element_blank()
    ),
  # 左下:保留x、y轴标题
  ggplot(df3, aes(x, y, fill = z)) +
    geom_raster(interpolate = TRUE) +
    theme_minimal() +
    theme(
      aspect.ratio = 1,
      legend.position = "bottom",
      legend.box = "horizontal"
    ),
  # 右下:保留x轴标题,隐藏y轴标题
  ggplot(df4, aes(x, y, fill = z)) +
    geom_raster(interpolate = TRUE) +
    theme_minimal() +
    theme(
      aspect.ratio = 1,
      legend.position = "bottom",
      legend.box = "horizontal",
      axis.title.y = element_blank()
    )
)

plot_aspr <- wrap_plots(
    p_tmp,
    nrow = 2,
    ncol = 2,
    guides = "collect"
  ) +
  plot_annotation(
    title = "Emission-Excitation-Matrix",
    subtitle = "Rayleigh Filtered Data") &
  scale_fill_viridis_c(limits = c(min_z, max_z)) &
  coord_cartesian(expand = FALSE)

print(plot_aspr)

内容的提问来源于Stack Exchange,提问作者Excelsior

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:23:19