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

如何让ggplot中两张图的主次Y轴范围保持一致?

解决ggplot2拆分数据后主次Y轴范围不一致问题

要让拆分后的两张图主次Y轴范围完全一致(主Y轴0-1200,次Y轴0-90),核心是手动指定Y轴的固定范围,避免ggplot自动根据子集数据调整范围。具体修改如下:

修改后完整代码

library(forcats)
library(tidyr)
library(ggplot2)

# 原始数据
mydata<-data.frame(id=c(1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12),
                   mean=c(80,80,53,53,46,46,42,42,37,37,33,33,
                          28,28,22,22,20,20,17,17,10,10,8,8),
                   type=rep(c("dead","survived"),12),
                   value=c(46,130,220,980,20,840,13,452,8,350,5,69,
                           4,536,16,141,0,55,38,168,12,95,42,170))

# 拆分数据
mydata1<-mydata[which(mydata$id %in% c(1:6)),]
mydata2<-mydata[which(mydata$id %in% c(7:12)),]

# 绘制第一张图(ID1-6)
mydata1%>%
  ggplot(aes(x=factor(id),
             y=value, fill=factor(type,levels=c("dead","survived"))))+
  geom_bar(position=position_stack(),stat="identity") + 
  geom_text(data=subset(mydata1,value != 0),
            aes(label = value),position=position_stack(vjust=0.5),size=4) +
  # 调整mean缩放比例,匹配主Y轴0-1200与次Y轴0-90的对应关系
  geom_line(color='grey30', linewidth=0.5, aes(x = id, y = mean*(1200/90), group=1)) +
  geom_point(aes(x=id,y=mean*(1200/90))) + 
  geom_text(aes(label = mean,y=mean*(1200/90)+30),size=3.5) + 
  theme(legend.position = c(0.90,0.85)) +
  labs(x="Site ID",y="",fill="Num of pts") +  
  scale_y_continuous(
    breaks = seq(0, 1200, 60), 
    name="num of pts",
    # 强制主Y轴范围固定为0-1200
    limits = c(0, 1200),
    # 转换函数确保主Y轴1200对应次Y轴90
    sec.axis = sec_axis(~.*(90/1200), name="mean events",breaks = seq(0, 90, 10))
  )

# 绘制第二张图(ID7-12)
mydata2%>%
  ggplot(aes(x=factor(id),
             y=value, fill=factor(type,levels=c("dead","survived"))))+
  geom_bar(position=position_stack(),stat="identity") + 
  geom_text(data=subset(mydata2,value != 0),
            aes(label = value),position=position_stack(vjust=0.5),size=4) +
  geom_line(color='grey30', linewidth=0.5, aes(x = id, y = mean*(1200/90), group=1)) +
  geom_point(aes(x=id,y=mean*(1200/90))) + 
  geom_text(aes(label = mean,y=mean*(1200/90)+30),size=3.5) + 
  theme(legend.position = c(0.90,0.85)) +
  labs(x="Site ID",y="",fill="Num of pts") +  
  scale_y_continuous(
    breaks = seq(0, 1200, 60), 
    name="num of pts",
    limits = c(0, 1200),
    sec.axis = sec_axis(~.*(90/1200), name="mean events",breaks = seq(0, 90, 10))
  )

关键修改点

  • 在scale_y_continuous中添加limits = c(0, 1200),强制主Y轴范围固定,避免ggplot根据子集数据自动缩小范围。
  • 调整次Y轴转换函数为~.*(90/1200),确保主Y轴最大值1200对应次Y轴的90,实现次Y轴范围0-90。
  • 同步调整mean的缩放比例为mean*(1200/90),保证mean数值能正确映射到主Y轴,同时在次Y轴显示对应数值。
  • 微调geom_text的Y偏移量,避免标签超出固定的Y轴范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 10:55:54