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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:30:54