如何在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快速实现分组聚类
这是最简洁的方式,通过分面自动将每组正负样本归为一类,添加分组标签:
- 给数据添加分组变量(从
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"))
- 修改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效果)
若不想用分面,可手动计算位置添加标签和分割线:
- 先确定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)
- 修改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
相关产品推荐
相关产品推荐

