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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:00:32