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
相关产品推荐
相关产品推荐

