如何用R(优先ggplot)绘制共享Y轴、双X轴的水平双柱状图
在R中绘制共享Y轴的双水平柱状图(金字塔图)
要实现共享Y轴的双水平柱状图(类似金字塔布局),不需要拼接独立图表,直接用ggplot的图层叠加就能搞定。核心思路是把其中一个变量取负值,让它在Y轴左侧显示,另一个在右侧,再调整坐标轴细节即可。
1. 导入并准备数据
先把样本数据读入R,这里直接构造数据框(也可以用read.csv读取本地文件):
# 构造样本数据框 gene_data <- data.frame( gene = c("VHL", "PBRM1", "NF2", "PTEN", "EGFR", "NF1", "PIK3CA", "BAP1", "TP53", "CDH1", "MET", "SMAD4", "RB1", "APC", "PPP6C", "NSD1", "TSC1", "ALB", "ATM", "STK11"), mutations = c(165, 145, 21, 122, 98, 16, 91, 18, 58, 117, 22, 33, 30, 45, 23, 19, 28, 48, 18, 12), proportion = c(0.491, 0.355, 0.209, 0.199, 0.181, 0.172, 0.15, 0.139, 0.127, 0.085, 0.075, 0.075, 0.055, 0.05, 0.047, 0.04, 0.039, 0.037, 0.035, 0.033) ) # 将gene转为因子,锁定原始顺序(避免ggplot自动排序) gene_data$gene <- factor(gene_data$gene, levels = gene_data$gene) # 把proportion转为负值,用于左侧柱状图 gene_data$neg_proportion <- -gene_data$proportion
2. 用ggplot绘制双水平柱状图
通过叠加两个geom_col图层实现左右对称布局,再调整坐标轴和主题优化显示:
library(ggplot2) ggplot(gene_data) + # 左侧柱状图:proportion(负值) geom_col(aes(x = neg_proportion, y = gene), fill = "#2c3e50", width = 0.6) + # 右侧柱状图:mutations计数 geom_col(aes(x = mutations, y = gene), fill = "#e74c3c", width = 0.6) + # 自定义X轴刻度:左侧显示正数,右侧显示原始计数 scale_x_continuous( breaks = c(-0.4, -0.2, 0, 50, 100, 150), labels = c("0.4", "0.2", "0", "50", "100", "150"), expand = c(0, 0) # 去掉坐标轴两端空白 ) + # 反转Y轴,让基因从上到下匹配原始数据顺序 scale_y_discrete(limits = rev(levels(gene_data$gene))) + # 基础标签设置 labs( x = "", y = "Gene", title = "Gene Mutations vs Proportion" ) + # 手动添加两侧X轴标题 annotate("text", x = -0.2, y = length(gene_data$gene) + 1, label = "Proportion", color = "#2c3e50", size = 4) + annotate("text", x = 75, y = length(gene_data$gene) + 1, label = "Mutations Count", color = "#e74c3c", size = 4) + # 添加Y轴垂直参考线 geom_vline(xintercept = 0, color = "black", linetype = "solid") + # 美化主题 theme_minimal() + theme( plot.title = element_text(hjust = 0.5, size = 14, face = "bold"), axis.text.y = element_text(size = 10), axis.text.x = element_text(size = 9), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(), panel.grid.major.y = element_line(color = "#f0f0f0") )
关键逻辑说明
- 将
proportion转为负值:让柱子自动排列在Y轴左侧,与右侧的mutations形成对称布局。 - 自定义X轴刻度:把左侧的负数值转为正数显示,避免用户混淆。
- 反转Y轴:保证基因顺序与原始数据一致,便于对照查看。
- 手动添加双X轴标题:利用
annotate绕过ggplot单X轴标题的限制,实现两侧分别标注。
可选替代方案
如果不想手动处理负值,也可以使用ggstance包的geom_colh函数,核心逻辑仍是通过坐标轴方向调整实现对称,但上面的原生ggplot方案无需额外安装包,更轻量化。
内容的提问来源于stack exchange,提问作者NullPumpkinException
相关产品推荐
相关产品推荐

