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

ggplot2双Y轴柱状图实现并列而非叠加的方法求助

解决ggplot2双Y轴柱状图并列显示的问题

首先得说明:ggplot2本身不推荐使用双Y轴,因为很容易让读者对数据产生误解,但如果你的需求确实需要双Y轴,我们可以通过手动调整X轴位置的方式实现柱子并列,而非叠加显示。

核心解决方案:手动偏移X轴位置

由于两个geom_bar对应不同的Y变量,无法直接用position_dodge(它适合同一X分组下的不同类别),所以我们可以把date因子转换成数值,给每个柱子分别偏移固定值,实现并列效果。同时还要修正你原来的右侧Y轴刻度计算(之前的转换逻辑有误)。

修改后的完整代码如下:

library(ggplot2)

# 你的数据集
mergedaph1 <- structure(list(date = structure(1:3, .Label = c("2018-07-12", "2018-09-09", "2019-08-01"), class = "factor"), 
                             Maturity = c(0.35, 0.02, NA), 
                             daphnia = c(0.0249, 0.0256, 0)), 
                        class = "data.frame", row.names = c(NA, -3L))

pa2 <- ggplot(data = mergedaph1) + 
  # Maturity柱子:向左偏移0.2,设置灰色填充
  geom_bar(aes(x = as.numeric(date) - 0.2, y = Maturity), 
           stat = 'identity', fill = "grey61", width = 0.4) + 
  # Daphnia柱子:向右偏移0.2,白填充黑边框,便于区分
  geom_bar(aes(x = as.numeric(date) + 0.2, y = daphnia * 5), 
           stat = 'identity', color = "black", fill = "white", width = 0.4) + 
  # 还原X轴刻度为原始日期
  scale_x_continuous(breaks = 1:3, labels = levels(mergedaph1$date)) +
  # 修正右侧Y轴:daphnia乘5适配左侧刻度,右侧需除以5还原真实值
  scale_y_continuous(
    name = "Maturity rate",
    sec.axis = sec_axis(
      ~ . / 5, 
      name = "Abundance (ind/L)",
      labels = function(b) round(b, 2)
    )
  ) + 
  # 调整辅助线位置:适配新X轴的离散刻度
  geom_vline(xintercept = c(1.5, 2.5), lty = 2, size = .8) + 
  xlab("Date") + 
  theme_bw() + 
  theme(
    panel.background = element_blank(), 
    panel.grid.major = element_blank(), 
    panel.grid.minor = element_blank(), 
    plot.background = element_blank(), 
    axis.text=element_text(size=15), 
    axis.title=element_text(size=17), 
    axis.text.y.left = element_text(color = "grey55", size = 15), 
    axis.title.y.left = element_text(color = "grey55", size = 17), 
    axis.text.y.right = element_text(color = "black", size = 15), 
    axis.title.y.right = element_text(color = "black", size = 17)
  )

pa2

关键修改点说明:

  1. X轴偏移:把date因子转成数值后,给两个柱子分别加减0.2,让它们在同一日期下并列,同时设置柱子宽度为0.4避免重叠。
  2. 右侧Y轴修正:你之前的sec_axis(~./1)逻辑错误,因为daphnia是乘5后适配左侧刻度的,右侧轴需要除以5才能还原真实的丰度值。
  3. 柱子样式优化:给第二个柱子添加白色填充,和灰色的Maturity柱子形成更清晰的视觉区分。

提升图表可读性的建议

  1. 添加图例:目前两个柱子没有说明,读者无法区分对应指标。可以给每个geom_bar添加aes(fill=...),手动设置图例:
    pa2 <- pa2 +
      aes(fill = "Maturity") +
      geom_bar(aes(x = as.numeric(date) + 0.2, y = daphnia * 5, fill = "Daphnia Abundance"), 
               stat = 'identity', color = "black", width = 0.4) +
      scale_fill_manual(
        values = c("Maturity" = "grey61", "Daphnia Abundance" = "white"),
        name = "Measurement"
      )
    
  2. 处理NA值:Maturity在2019-08-01有NA值,柱子会缺失,可以添加geom_text标注“NA”,或者在图注中说明缺失情况。
  3. 调整辅助线逻辑:你原来的辅助线计算基于日期占全年的比例,但现在X轴是离散的三个日期,建议把辅助线放在日期之间(比如xintercept=1.5对应2018-07和2018-09之间),更符合当前X轴的逻辑。
  4. 统一视觉风格:可以把图例的字体大小调整到和轴标签一致,保持整体视觉统一;也可以给柱子添加轻微的圆角(geom_bar(..., color="black", size=0.5)),让图表更柔和。
  5. 考虑替代方案:如果允许的话,优先考虑用分面图(facet_wrap(~metric, ncol=1))替代双Y轴,把两个指标分成上下子图,这样更符合ggplot2的设计理念,也避免双Y轴带来的误解。

内容的提问来源于stack exchange,提问作者Julien Beaulieu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 12:43:10