如何在双Y轴(不同刻度)的ggplot图中绘制清晰误差棒?
双Y轴ggplot2图表中EVI误差棒可视性问题
我尝试使用ggplot2绘制带有双Y轴的图表,但两个轴的刻度差异极大,其中EVI变量的误差棒因标准误过小难以在图中辨识。以下是我的代码:
date<-as.Date(c("2008-10-01","2009-09-01","2010-11-01","2011-09-01", "2012-10-01","2013-09-01","2014-09-01","2015-09-01", "2016-09-01","2017-09-01")) year2<-c(2008,2009,2010,2011,2012,2013,2014,2015,2016,2017) evi.total<-c(0.074,0.064,0.066,0.060,0.073,NA,0.064,0.073,0.076,0.076) densidad.total<-c(22.78,17.19,19.39,16.46,32.34,NA,13.62,26.41,26.05,34.77) se.dens.tot<-c(4.50, 4.76,4.13,3.93,7.75,NA,3.51,5.63,4.86,7.02) sd.evi.general<-c(0.011,0.010,0.011,0.010,0.011,NA,0.012,0.011,0.012,0.014) n<-c(5018,5018,5018,5018,5018,NA,5018,5018,5018,5018) se.evi<-sd.evi.general/(sqrt(n)) data<-data.frame(date,year2,evi.total,densidad.total,se.dens.tot,sd.evi.general, se.evi) library(ggplot2) p <- ggplot(data=data,aes(x = date)) p<-p + scale_x_date(date_breaks="3 month", date_labels = "%b-%y", ) p <- p + geom_line(aes(y =densidad.total, colour = "Guanaco's density"),size=.5)+ geom_linerange(aes(y=densidad.total,ymin=densidad.total-se.dens.tot, ymax=densidad.total+se.dens.tot), color="tomato1", size=1,lwd=.07) p <- p + geom_line (aes(y =evi.total*1000, colour = "EVI"),size=.5) + labs(color=NULL) + geom_linerange(aes(y=evi.total*1000, ymin=evi.total*1000-se.evi*1000, ymax=evi.total*1000+se.evi*1000), color="aquamarine4",size=1) p <- p + scale_y_continuous(sec.axis = sec_axis(~./1000, name = " EVI")) p <- p + scale_colour_manual(values = c("aquamarine4", "tomato1")) p <- p +theme_classic() p <- p + labs(y = expression ("Guanaco's density "(guanaco/~km^2), x = "", colour = "")) p <- p + theme(legend.position = "bottom")+ theme(text = element_text(size = 20,hjust = 1), axis.line.x = element_line(color="black", size = 1), axis.line.y = element_line(color="black", size = 1), axis.text.x=element_text(colour="black",angle=60, size=10), axis.text.y=element_text(colour="black")) p
我曾参考相关解决方案,但仍未解决误差棒可视性问题。
解决方案
1. 放大EVI误差棒显示比例
由于EVI的标准误极小,按原比例缩放后误差棒长度几乎不可见,可以手动放大误差棒的范围,同时在图表中明确标注该处理,避免误导。
修改EVI的geom_linerange代码:
geom_linerange(aes(y=evi.total*1000, ymin=evi.total*1000 - se.evi*1000*100, ymax=evi.total*1000 + se.evi*1000*100), color="aquamarine4", size=1)
同时在图表标题或图例中添加说明:EVI误差棒已放大100倍。
2. 拆分为独立子图(推荐)
双Y轴容易造成视觉误导,将两个指标拆分为上下独立的子图,各自使用适配的刻度,能彻底解决误差棒可视性问题,也更符合数据可视化规范。可以借助patchwork包实现:
# 安装并加载patchwork install.packages("patchwork") library(patchwork) # 绘制骆马密度图表 p1 <- ggplot(data=data,aes(x = date)) + scale_x_date(date_breaks="3 month", date_labels = "%b-%y") + geom_line(aes(y =densidad.total, colour = "Guanaco's density"),size=.5)+ geom_linerange(aes(y=densidad.total,ymin=densidad.total-se.dens.tot, ymax=densidad.total+se.dens.tot), color="tomato1", size=1,lwd=.07) + scale_colour_manual(values = "tomato1") + theme_classic() + labs(y = expression ("Guanaco's density "(guanaco/~km^2)), x = "") + theme(legend.position = "bottom", text = element_text(size = 20,hjust = 1), axis.line.x = element_line(color="black", size = 1), axis.line.y = element_line(color="black", size = 1), axis.text.x=element_text(colour="black",angle=60, size=10), axis.text.y=element_text(colour="black")) # 绘制EVI图表 p2 <- ggplot(data=data,aes(x = date)) + scale_x_date(date_breaks="3 month", date_labels = "%b-%y") + geom_line(aes(y =evi.total, colour = "EVI"),size=.5) + geom_linerange(aes(y=evi.total, ymin=evi.total-se.evi, ymax=evi.total+se.evi), color="aquamarine4",size=1) + scale_colour_manual(values = "aquamarine4") + theme_classic() + labs(y = "EVI", x = "") + theme(legend.position = "bottom", text = element_text(size = 20,hjust = 1), axis.line.x = element_line(color="black", size = 1), axis.line.y = element_line(color="black", size = 1), axis.text.x=element_text(colour="black",angle=60, size=10), axis.text.y=element_text(colour="black")) # 合并上下子图 p1 / p2
3. 调整EVI缩放系数
通过增大EVI的缩放倍数,让其数值范围更接近密度的刻度范围,从而间接增加误差棒长度。例如将原缩放系数1000改为5000:
# 修改EVI线条和误差棒的缩放 p <- p + geom_line (aes(y =evi.total*5000, colour = "EVI"),size=.5) + labs(color=NULL) + geom_linerange(aes(y=evi.total*5000, ymin=evi.total*5000-se.evi*5000, ymax=evi.total*5000+se.evi*5000), color="aquamarine4",size=1) # 调整右侧Y轴的转换公式 p <- p + scale_y_continuous(sec.axis = sec_axis(~./5000, name = " EVI"))
这种方式能提升误差棒可视性,但仍存在双Y轴的视觉歧义,需谨慎使用。
内容的提问来源于stack exchange,提问作者user228095
相关产品推荐
相关产品推荐

