如何复制分面箱线图的y轴范围并应用到另一幅箱线图?
问题
我想制作一组y轴范围完全一致的组合图,里面包含两幅分面箱线图。之前手动设置相同y轴范围时,会打乱左图的中位数和线条方向,所以左图必须用scale = "free_y"。现在想知道:
- 能不能直接复制左图的y轴范围,精准应用到右图?
- 有没有办法获取箱线图实际使用的精确y轴范围?
目前我尝试先获取左图(AbundancePlotVH)的y轴范围,再手动设置到右图(boxplotVHAbundance)上(右图手动设y轴不会破坏图表),但试了两种方法都不行:
- 用
par("usr"),得到的结果是0 1 0 1,完全不对; - 取左图数据的极值:
Range <- range(c(totalVH$MeanAbundance)) Range
这个有一定参考性,但没法让两个图的轴完全对齐。
我用来组合两幅图的代码是:
prow<- plot_grid(AbundancePlotVH + theme(legend.position="none"), boxplotVHAbundance + theme(legend.position="none", axis.text.y = element_blank(), axis.ticks.y = element_blank())) VH<- plot_grid(title, prow, legend, ncol = 1, rel_heights = c(1, 10), axis = "l", align = "v") VH
解决方案
方法1:提取ggplot对象的计算后y轴范围
ggplot绘制完图表后,会在对象里存储计算好的坐标轴范围。可以用以下代码提取左图的精确y轴范围:
# 渲染左图并获取布局信息 AbundancePlotVH_build <- ggplot_build(AbundancePlotVH) # 提取所有分面的y轴范围,合并后取全局极值 y_range <- range(unlist(lapply(AbundancePlotVH_build$layout$panel_params, function(x) x$y.range)))
然后将这个范围应用到右图:
boxplotVHAbundance_fixed <- boxplotVHAbundance + scale_y_continuous(limits = y_range)
最后用修正后的右图执行原组合代码即可。
方法2:用egg包自动对齐坐标轴
如果不想手动提取范围,可以用egg包的ggarrange函数,它支持自动对齐分面图的坐标轴,即使其中一个用了free_y:
library(egg) # 自动对齐两个图的y轴 prow <- ggarrange(AbundancePlotVH + theme(legend.position="none"), boxplotVHAbundance + theme(legend.position="none", axis.text.y = element_blank(), axis.ticks.y = element_blank()), align = "v") # 组合标题、对齐后的图和图例 VH <- plot_grid(title, prow, legend, ncol = 1, rel_heights = c(1, 10), axis = "l", align = "v") VH
方法3:手动计算箱线图的完整显示范围
箱线图的whiskers默认延伸至1.5倍四分位距处,因此可以手动计算这个完整范围,而非仅取数据极值:
# 计算左图数据的四分位距和whiskers边界 q <- quantile(totalVH$MeanAbundance, c(0.25, 0.75)) iqr <- q[2] - q[1] y_min <- q[1] - 1.5 * iqr y_max <- q[2] + 1.5 * iqr # 结合数据实际极值确定最终范围 y_range <- range(c(totalVH$MeanAbundance, y_min, y_max))
将这个范围赋值给右图的scale_y_continuous(limits = y_range),即可匹配左图箱线图的显示范围。
内容的提问来源于stack exchange,提问作者Thimo
相关产品推荐
相关产品推荐

