ggplot2轴自定义(间距/分段):分组分隔与栏宽调整实现
问题描述
现有一个ggplot生成的横向条形图,需要将变量划分为两个子集:
- 「6个月组」:包含变量
x1、x2 - 「基线组」:对应变量
baseline
需要实现两个定制需求:
- 在两个子集之间添加分隔间距
- 让两个子集的条形宽度不同
当前使用的代码及生成的图形如下:
library(ggplot2) library(ggnewscale) x1 = rep(1:3, times = 2) x2 = rep(c("Y", "N"), each = 3) baseline = rep(0:1, times = 3) y <- data.frame(x1,x2,baseline) Dat <- y |> mutate(across(everything(), as.character)) |> pivot_longer(everything(), names_to = "var") ggplot(Dat, aes(y = var)) + coord_flip() + geom_bar(data = ~subset(.x, var %in% c("x1")), aes(fill = value), position = "fill") + scale_fill_viridis_d(option = "B", guide = guide_legend(order = 3))+ new_scale_fill() + geom_bar(data = ~subset(.x, var %in% c("x2")), aes(fill = value), position = "fill") + scale_fill_brewer(palette = "Dark2", guide = guide_legend(order = 2)) + new_scale_fill() + geom_bar(data = ~subset(.x, var %in% c("baseline")), aes(fill = value), position = "fill") + scale_fill_brewer(palette = "Paired", guide = guide_legend(order = 1))

实现思路与代码
核心思路
- 子集分隔与间距:给变量添加分组标签,将
y轴映射为指定顺序的因子,通过position_nudge调整不同子集条形的位置,配合scale_y_discrete的expand参数强化子集间的分隔间距。 - 不同条形宽度:针对两个子集分别调用
geom_bar,设置不同的width参数,实现宽度差异。
所需包
仅需原代码中的ggplot2和ggnewscale,无需额外安装新包。
完整实现代码
library(ggplot2) library(ggnewscale) library(dplyr) # 用于数据处理 # 构造数据 x1 = rep(1:3, times = 2) x2 = rep(c("Y", "N"), each = 3) baseline = rep(0:1, times = 3) y <- data.frame(x1,x2,baseline) # 整理数据并添加分组标签 Dat <- y |> mutate(across(everything(), as.character)) |> pivot_longer(everything(), names_to = "var") |> # 标记每个变量所属的子集 mutate(group = case_when( var %in% c("x1", "x2") ~ "6-months", var == "baseline" ~ "baseline" )) |> # 指定变量顺序:先6个月组,再基线组,确保子集排列正确 mutate(var = factor(var, levels = c("x1", "x2", "baseline"))) ggplot(Dat, aes(y = var)) + coord_flip() + # 绘制6个月组条形:宽度0.8,位置左移实现间距 geom_bar(data = ~subset(.x, group == "6-months"), aes(fill = value), position = "fill", width = 0.8, position = position_nudge(y = -0.1)) + scale_fill_viridis_d(option = "B", guide = guide_legend(order = 3))+ new_scale_fill() + # 绘制基线组条形:宽度0.6,位置右移实现间距 geom_bar(data = ~subset(.x, group == "baseline"), aes(fill = value), position = "fill", width = 0.6, position = position_nudge(y = 0.2)) + scale_fill_brewer(palette = "Paired", guide = guide_legend(order = 1)) + # 调整y轴刻度的扩展间距,进一步拉开子集距离 scale_y_discrete(expand = expansion(add = c(0.5, 0.5))) + labs(y = "")
效果说明
- 两个子集通过位置偏移和轴刻度扩展实现了清晰的分隔间距
- 6个月组条形宽度为0.8,基线组为0.6,满足宽度差异化需求
- 保留了原有的多组独立填充色设置
内容的提问来源于stack exchange,提问作者EB3112
相关产品推荐
相关产品推荐

