如何基于Specie列重新排序ggplot分组柱状图的显示顺序
问题描述
我想用ggplot绘制分组柱状图,要求按Specie列排序:先展示sp1的基因型对应的柱状图,然后是sp2,最后是sp3;同时每个物种内的柱状图要按var值降序排列。目前已经画出图表,但顺序不符合要求,以下是我用的代码和数据集:
ggplot(data=data, aes(x=reorder(Genotype, -var) , y=var, fill=Treatment)) + geom_bar(stat="identity", position=position_dodge(width=0.85)) + scale_fill_manual(values = c('#4850CE','#D37A3E'), labels = c("Control Temperature (CT)","Heat tress (HS)")) + geom_errorbar(aes(ymin = var, ymax = var+e,colour=Treatment), width=0.75, position = position_dodge(0.85))+ scale_colour_manual(values=c('#4850CE','#D37A3E'))+ theme_bw() + labs(x=NULL, y=expression("a. weight"^~g))+ scale_y_continuous(breaks = seq(0, max(data$var+data$e), length.out = 6), labels = number_format(accuracy = 0.01))+ geom_text(aes(label = Genotype, y = 0),angle=90, hjust=0, size=3)+ theme(panel.grid.minor = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.y = element_text(colour = "black", size=8, face="bold"), axis.ticks.y = element_line(colour= "black"), axis.text.y =element_text(colour="black", size = 8), legend.position = c(0.8, 0.92), legend.background = element_blank(), legend.key.size = unit(4, 'mm'), legend.title = element_blank(), legend.text = element_text(size = 8,face="bold"))+ guides(colour = FALSE)
数据集
| Genotype | Specie | Treatment | var | e |
|---|---|---|---|---|
| BGB094 | sp1 | CT | 185.9406 | 44.7377 |
| BGB095 | sp1 | CT | 248.2271 | 44.7377 |
| BGB097 | sp2 | CT | 162.4696 | 44.7377 |
| BGB001 | sp2 | CT | 284.5522 | 44.7377 |
| BGB011 | sp3 | CT | 185.5353 | 44.7377 |
| BGB048 | sp3 | CT | 219.0846 | 44.7377 |
| BGB094 | sp1 | HS | 150.9137 | 44.7377 |
| BGB095 | sp1 | HS | 211.05 | 44.7377 |
| BGB097 | sp2 | HS | 123.8366 | 44.7377 |
| BGB001 | sp2 | HS | 247.2338 | 44.7377 |
| BGB011 | sp3 | HS | 149.6919 | 44.7377 |
| BGB048 | sp3 | HS | 184.7978 | 44.7377 |
解决方案
要实现先按Specie排序(sp1→sp2→sp3),再在每个物种内按var降序排列Genotype,需要提前自定义Genotype的因子顺序,而不是仅用reorder函数。
步骤1:预处理数据,确定排序规则
先基于每个基因型的平均var值(覆盖CT和HS两个处理),结合物种顺序确定最终排序:
library(dplyr) # 计算每个基因型的平均var值,按指定物种顺序+var降序排列 sorted_genotypes <- data %>% group_by(Genotype, Specie) %>% summarise(mean_var = mean(var), .groups = "drop") %>% arrange(factor(Specie, levels = c("sp1", "sp2", "sp3")), desc(mean_var)) %>% pull(Genotype) # 将Genotype转换为因子,指定自定义顺序 data$Genotype <- factor(data$Genotype, levels = sorted_genotypes)
步骤2:修改ggplot代码
把原代码中x=reorder(Genotype, -var)替换为x=Genotype,因为已经提前设置好因子顺序:
ggplot(data=data, aes(x=Genotype, y=var, fill=Treatment)) + geom_bar(stat="identity", position=position_dodge(width=0.85)) + scale_fill_manual(values = c('#4850CE','#D37A3E'), labels = c("Control Temperature (CT)","Heat stress (HS)")) + # 修正拼写错误tress→stress geom_errorbar(aes(ymin = var, ymax = var+e,colour=Treatment), width=0.75, position = position_dodge(0.85))+ scale_colour_manual(values=c('#4850CE','#D37A3E'))+ theme_bw() + labs(x=NULL, y=expression("a. weight"^~g))+ scale_y_continuous(breaks = seq(0, max(data$var+data$e), length.out = 6), labels = scales::number_format(accuracy = 0.01))+ # 加scales::前缀避免函数找不到 geom_text(aes(label = Genotype, y = 0),angle=90, hjust=0, size=3)+ theme(panel.grid.minor = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.title.y = element_text(colour = "black", size=8, face="bold"), axis.ticks.y = element_line(colour= "black"), axis.text.y =element_text(colour="black", size = 8), legend.position = c(0.8, 0.92), legend.background = element_blank(), legend.key.size = unit(4, 'mm'), legend.title = element_blank(), legend.text = element_text(size = 8,face="bold"))+ guides(colour = FALSE)
说明
- 用平均
var值排序,确保每个基因型的整体水平作为排序依据,而非单个处理的数值 - 通过
factor(Specie, levels = c("sp1", "sp2", "sp3"))强制指定物种的展示顺序 - 因子顺序设置完成后,ggplot会自动按照该顺序绘制柱状图
内容的提问来源于stack exchange,提问作者Ikram Bashir
相关产品推荐
相关产品推荐

