如何用patchwork实现多图共享点图例且保留各自填充图例?
问题解决:Patchwork多面板图共享指定图例,保留子图填充图例
需求说明
- 多面板图共享点的**颜色(treat)、形状(top)、透明度(top)**图例
- 每个子图保留自身的**填充(fill=total)**图例(不同子图的填充数值范围存在差异,需保留特异性)
- 当前使用
plot_layout(guides = "collect")会将所有图例(包括填充图例)收集,导致填充图例重复或丢失子图特异性
解决方案
核心思路是仅收集需要共享的图例类别,让填充图例保留在每个子图中。通过patchwork的collect_guides()函数精准指定要收集的图例(color、shape、alpha),排除填充图例(fill)。
修改后的完整代码
library(ggplot2) library(dplyr) library(patchwork) library(ggrepel) set.seed(123) # 设置随机种子保证结果可重复 df1 <- data.frame(site = rep(c("a","b","c"),each=10), treat = rep(c("treat_1","treat_2"),each=5), species = rep(c("spA","spB","spC","spD","spE")), val = rpois(30,10)) df1$val2 <- NA df1$val2[df1$species == "spA"] <- 15 df1$val2[df1$species == "spB"] <- 10 df1$val2[df1$species == "spC"] <- 12 df1$val2[df1$species == "spD"] <- 8 df1$val2[df1$species == "spE"] <- 5 df1$top <- NA df1$top[df1$species == "spA"] <- "top_1" df1$top[df1$species == "spB"] <- "top_2" df1$top[df1$species == "spC"] <- "top_3" df1$top[df1$species == "spD"] <- "none" df1$top[df1$species == "spE"] <- "none" ### Contour plot 生成函数 contour_plot <- function(data, site_name) { site_data <- data %>% filter(site == site_name) value_2 <- seq(min(site_data$val2), max(site_data$val2), length.out = 50) value_1 <- seq(min(site_data$val), max(site_data$val), length.out = 50) grid_df <- expand.grid(anomaly = value_2, abun = value_1) %>% mutate(total = anomaly * abun) top_contributors <- site_data %>% filter(top %in% c("top_1", "top_2", "top_3") & treat == "treat_1") p <- ggplot(grid_df, aes(x = anomaly, y = abun)) + geom_tile(aes(fill = total)) + geom_contour(aes(z = total), color = "gray50") + geom_point(data = site_data, aes(x = val2, y = val, color = treat, alpha = top, shape = top), size=3) + scale_alpha_manual(values = c("top_1" = 1, "top_2" = 1, "top_3" = 1, "none" = 0.4), labels = c("top_1" = "Top 1", "top_2" = "Top 2", "top_3" = "Top 3", "none" = "N/A")) + scale_shape_manual(values = c("top_1" = 8, "top_2" = 18, "top_3" = 17, "none" = 20), labels = c("top_1" = "Top 1", "top_2" = "Top 2", "top_3" = "Top 3", "none" = "N/A")) + scale_fill_gradient2( low = "blue", mid = "white", high = "red", midpoint = 0, guide = guide_colorbar(title = "Total") # 明确填充图例标题,保证子图显示一致性 ) + ggtitle(site_name) + geom_label_repel(data = top_contributors, aes(x = val2, y = val, label = species), size = 3, box.padding = 0.5, point.padding = 0.3, fill = "white", color = "black", nudge_x = 0.1, nudge_y = 0.0001, min.segment.length = unit(0, 'lines'), segment.color = 'grey50') + theme_minimal() + theme(axis.text.x = element_text(size = 12), axis.text.y = element_text(size = 14), axis.title = element_text(size = 14, face = "bold"), legend.position = "right") # 让填充图例显示在子图右侧 p # 返回绘图对象,避免提前输出 } # 批量生成并存储子图 plots_contours <- lapply(unique(df1$site), function(site) contour_plot(df1, site)) ### 多面板图组合:仅收集指定图例 wrap_plots(plots_contours, ncol=2, nrow=2) + plot_layout( guides = collect_guides(guides = c("color", "shape", "alpha")), # 仅收集点相关的共享图例 axis_titles = "collect" ) + plot_annotation(title = "Site-specific Contour Plots", theme = theme(title = element_text(size=16, face="bold"))) # 可选:添加总标题
关键修改点
- 子图生成优化:移除
print(p),直接返回绘图对象,保证patchwork能正确处理 - 填充图例配置:给
scale_fill_gradient2添加guide = guide_colorbar(),明确保留子图的填充图例 - 图例收集控制:用
collect_guides(guides = c("color", "shape", "alpha"))替代全局"collect",精准指定要共享的图例类别,填充图例自动保留在每个子图中 - 可重复性保障:添加
set.seed(123)保证随机生成的数据可重复
内容的提问来源于stack exchange,提问作者millie0725
相关产品推荐
相关产品推荐

