如何在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根据这个权重控制堆叠顺序。具体步骤如下:
- 针对每个time值定义对应的type排序规则,将type转换为用于排序的数值
- 通过
case_when将排序规则整合到原始数据,生成新的排序变量 - 修改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
相关产品推荐
相关产品推荐

