如何在ggplot堆叠条形图与冲积图中实现图例分组?
通用ggplot图例分组方案(适配堆叠条形图&ggalluvial冲积图)
问题说明
需要将图例按A&B、C&D分为两组,现有两个场景无法用常规方法解决:
- 堆叠条形图:误以为堆叠图是不可拆分的整体,无法通过多次调用
geom_bar实现分组 - ggalluvial冲积图:常规
geom_col方案不适用
解决方案:基于ggnewscale的拆分绘图法
核心思路是按图例分组拆分数据子集,对每个子集单独绘制并设置独立图例,用ggnewscale隔离不同组的美学映射,既保持图形原有结构,又实现图例分组。
1. 堆叠条形图实现代码
library(ggplot2) library(ggnewscale) # 原数据和颜色定义 col_define = c('red', 'orange', 'blue', 'lightblue') names(col_define) = c('A', 'B', 'C', 'D') data = rbind( data.frame('grp1' = 'X', 'grp2' = c('A', 'B', 'C', 'D'), 'val' = c(1,2,3,4)), data.frame('grp1' = 'Y', 'grp2' = c('A', 'B', 'C', 'D'), 'val' = c(1,2,3,4)+2) ) ggplot() + # 绘制A&B组堆叠部分 geom_bar(data = subset(data, grp2 %in% c("A", "B")), aes(x = grp1, fill = grp2, y = val), stat = 'identity', position = 'stack') + scale_fill_manual(name = "Group 1 (A&B)", values = col_define[c("A", "B")], breaks = c("A", "B")) + # 启用新的填充图例空间 new_scale_fill() + # 绘制C&D组堆叠部分 geom_bar(data = subset(data, grp2 %in% c("C", "D")), aes(x = grp1, fill = grp2, y = val), stat = 'identity', position = 'stack') + scale_fill_manual(name = "Group 2 (C&D)", values = col_define[c("C", "D")], breaks = c("C", "D"))
注:拆分绘制的堆叠部分最终视觉效果和原整体堆叠图完全一致,只是通过拆分数据实现了图例分组。
2. ggalluvial冲积图实现代码
library(ggalluvial) library(ggnewscale) # 沿用原data和col_define ggplot() + # 绘制A&B组的冲积流和分层块 geom_flow(data = subset(data, grp2 %in% c("A", "B")), aes(x = grp1, stratum = grp2, alluvium = grp2, y = val, fill = grp2), alpha = .3) + geom_stratum(data = subset(data, grp2 %in% c("A", "B")), aes(x = grp1, stratum = grp2, y = val, fill = grp2, color = grp2), alpha = .9) + # 设置A&B组的填充和颜色图例 scale_fill_manual(name = "Group 1 (A&B)", values = col_define[c("A", "B")], breaks = c("A", "B")) + scale_color_manual(name = "Group 1 (A&B)", values = col_define[c("A", "B")], breaks = c("A", "B")) + # 分别启用新的填充、颜色图例空间 new_scale_fill() + new_scale_color() + # 绘制C&D组的冲积流和分层块 geom_flow(data = subset(data, grp2 %in% c("C", "D")), aes(x = grp1, stratum = grp2, alluvium = grp2, y = val, fill = grp2), alpha = .3) + geom_stratum(data = subset(data, grp2 %in% c("C", "D")), aes(x = grp1, stratum = grp2, y = val, fill = grp2, color = grp2), alpha = .9) + # 设置C&D组的填充和颜色图例 scale_fill_manual(name = "Group 2 (C&D)", values = col_define[c("C", "D")], breaks = c("C", "D")) + scale_color_manual(name = "Group 2 (C&D)", values = col_define[c("C", "D")], breaks = c("C", "D"))
注:冲积图需同时处理
fill和color两个美学映射,因此要分别调用new_scale_fill()和new_scale_color()来隔离不同组的图例。
通用逻辑总结
所有场景的核心步骤都是:
- 按图例分组要求拆分数据子集
- 对每个子集单独调用对应的绘图geom
- 为每个子集配置独立的图例名称、颜色映射
- 用
ggnewscale分隔不同组的美学图例,避免冲突
内容的提问来源于stack exchange,提问作者Bogaso
相关产品推荐
相关产品推荐

