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

如何在ggplot2柱状图的X轴添加子标题(分组聚类标注)

问题描述

我用ggplot2绘制了一幅柱状图,想进一步对X轴进行标注,把现有组别聚类为转化组(效果类似Excel的分组图表)。请问怎么用ggplot2实现?

我的代码如下:

DNAngPERuL <- 160
DNAug <- DNAngPERuL * 6 / 1000
colony_data_frequency <- colony_data / DNAug

transf_data <- data.frame(Selection=rep(c('Ntc 200 μg/mL', 'Zeo 25 μg/mL'), each=12),
                 biorep=rep(c('1', '1(-ve)', '2', '2(-ve)', '3', '3(-ve)', '4', '4(-ve)', '5', '5(-ve)', '6', '6(-ve)'), times=2),
                 colonies=colony_data_frequency)

# Plot
ggplot(data=transf_data, aes(fill=Selection, x=biorep, y=colonies)) +
  geom_bar(position = "dodge", stat="identity", colour="#434343", linetype = "solid") + 
  theme_classic() + 
  labs(title="Transformation Frequency", x="Bioreplicate", y = "No. of colonies / μg of DNA") + 
  theme(plot.title = element_text(hjust = 0.5)) + 
  scale_fill_manual(values=c("#3288bd", "#66C2A5")) + 
  scale_y_continuous(expand = expansion(mult = c(0, .1)))

当前图表效果:X轴按biorep依次排列1、1(-ve)、2、2(-ve)...6、6(-ve),每个biorep对应两个不同颜色的柱子(Ntc和Zeo组),无分组标注与分割。
目标效果:将X轴的1/1(-ve)、2/2(-ve)...6/6(-ve)分别聚类为独立组别,每组上方添加分组标签(如“转化组1”“转化组2”),组与组之间用分割线区分。


解决方案

方法1:用facet_wrap快速实现分组聚类

这是最简洁的方式,通过分面自动将每组正负样本归为一类,添加分组标签:

  1. 给数据添加分组变量(从biorep中提取组号):
# 提取组号,去掉(-ve)后缀
transf_data$group <- gsub("\\(-ve\\)", "", transf_data$biorep)
# 转换为因子,保证组顺序正确
transf_data$group <- factor(transf_data$group, levels = c("1", "2", "3", "4", "5", "6"))
  1. 修改ggplot代码,添加分面配置:
ggplot(data=transf_data, aes(fill=Selection, x=biorep, y=colonies)) +
  geom_bar(position = "dodge", stat="identity", colour="#434343", linetype = "solid") + 
  theme_classic() + 
  labs(title="Transformation Frequency", x="Bioreplicate", y = "No. of colonies / μg of DNA") + 
  theme(
    plot.title = element_text(hjust = 0.5),
    # 隐藏分面背景,将标签移至X轴上方
    strip.background = element_blank(),
    strip.placement = "outside"
  ) + 
  scale_fill_manual(values=c("#3288bd", "#66C2A5")) + 
  scale_y_continuous(expand = expansion(mult = c(0, .1))) +
  # 按group分面,X轴自由缩放,标签置于底部(X轴上方)
  facet_wrap(~group, scales = "free_x", strip.position = "bottom")

方法2:手动添加分组标签与分割线(贴近Excel效果)

若不想用分面,可手动计算位置添加标签和分割线:

  1. 先确定X轴元素的位置:
# 固定biorep的顺序,避免乱序
transf_data$biorep <- factor(transf_data$biorep, 
                             levels = c('1', '1(-ve)', '2', '2(-ve)', '3', '3(-ve)', '4', '4(-ve)', '5', '5(-ve)', '6', '6(-ve)'))
# 计算每组的中心位置(每组两个biorep,取中间值)
group_centers <- c(1.5, 3.5, 5.5, 7.5, 9.5, 11.5)
# 计算组之间的分割线位置
split_lines <- c(2.5, 4.5, 6.5, 8.5, 10.5)
  1. 修改ggplot代码,添加标注元素:
ggplot(data=transf_data, aes(fill=Selection, x=biorep, y=colonies)) +
  geom_bar(position = "dodge", stat="identity", colour="#434343", linetype = "solid") + 
  # 添加组间分割线
  annotate("segment", x = split_lines, xend = split_lines, y = 0, yend = Inf, 
           colour = "black", linetype = "dashed") +
  # 添加分组标签(置于X轴下方)
  annotate("text", x = group_centers, y = -max(transf_data$colonies)*0.05, 
           label = paste("转化组", 1:6), size = 4) +
  theme_classic() + 
  labs(title="Transformation Frequency", x="Bioreplicate", y = "No. of colonies / μg of DNA") + 
  theme(
    plot.title = element_text(hjust = 0.5),
    # 调整X轴文字下方空间,容纳分组标签
    axis.text.x = element_text(margin = margin(t = 10)),
    # 调整X轴标题位置,避免与标签重叠
    axis.title.x = element_text(margin = margin(t = 20))
  ) + 
  scale_fill_manual(values=c("#3288bd", "#66C2A5")) + 
  # 扩展Y轴下方空间,防止标签被截断
  scale_y_continuous(expand = expansion(mult = c(0.1, .1)))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 22:13:15