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

如何在ggplot2中为不同time组自定义fill堆叠顺序?

为不同time组自定义柱状图堆叠顺序

原始代码

library(ggplot2)
library(dplyr)

series <- data.frame(
  time = c(rep(1, 4),rep(2, 4), rep(3, 4), rep(4, 4)),
  type = rep(1984:1987, 4),
  value = rpois(16, 10)
)

series %>%
  ggplot(aes(time, value, group=factor(type, levels=1987:1984)))+
  geom_col(aes(fill= factor(type)))+
  guides(fill=guide_legend(title="type"))

需求说明

当前代码生成的分组柱状图中fill的堆叠顺序固定,需要为不同time组自定义fill(对应type)的堆叠顺序:

  • time 1:顺序为1984、1985、1986、1987
  • time 2:顺序为1984、1986、1985、1987
  • time 3:顺序为1984、1985、1987、1986
  • time 4:顺序为1987、1986、1985、1984

实现方法

要实现不同time组的自定义堆叠顺序,核心是为每个time组内的type分配专属排序权重,让ggplot根据这个权重控制堆叠顺序。具体步骤如下:

  1. 针对每个time值定义对应的type排序规则,将type转换为用于排序的数值
  2. 通过case_when将排序规则整合到原始数据,生成新的排序变量
  3. 修改ggplot的分组依据为新排序变量,同时保留原始type的fill映射以保证图例正常显示

完整代码

library(ggplot2)
library(dplyr)

set.seed(123) # 设置随机种子保证结果可复现
series <- data.frame(
  time = c(rep(1, 4),rep(2, 4), rep(3, 4), rep(4, 4)),
  type = rep(1984:1987, 4),
  value = rpois(16, 10)
)

# 添加自定义排序变量,每个time组内的type对应不同排序位置
series <- series %>%
  mutate(
    stack_order = case_when(
      time == 1 ~ match(type, c(1984, 1985, 1986, 1987)),
      time == 2 ~ match(type, c(1984, 1986, 1985, 1987)),
      time == 3 ~ match(type, c(1984, 1985, 1987, 1986)),
      time == 4 ~ match(type, c(1987, 1986, 1985, 1984)),
      TRUE ~ NA_real_
    )
  )

# 绘制柱状图,用stack_order控制堆叠顺序
series %>%
  ggplot(aes(time, value, group = stack_order)) +
  geom_col(aes(fill = factor(type)), position = position_stack(reverse = FALSE)) +
  guides(fill = guide_legend(title = "type"))

代码解释

  • stack_order变量:通过match函数将每个time组内的type映射为1-4的排序位置,数值越小在堆叠时越靠下(若需反转可调整position_stack的reverse参数为TRUE)
  • group = stack_order:让ggplot基于这个排序变量分组,从而实现不同time组的自定义堆叠顺序
  • 保留fill = factor(type):确保图例显示的是原始type值,不影响可读性

内容的提问来源于stack exchange,提问作者KGB91

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 07:18:21