ggplot调整双Y轴范围实现左侧轴0居顶、右侧轴0居底
解决方案
核心通过调整主Y轴范围、负值数据的映射规则,配合次轴线性转换即可实现需求,调整后可直接运行的代码如下:
library(tidyverse) library(ggplot2) # 预计算最大值和缩放因子 max_navy <- max(use_deciles$coef_navy, na.rm = T) max_abs_maroon <- max(abs(use_deciles$coef_maroon), na.rm = T) scl <- max_navy / max_abs_maroon ggplot(use_deciles) + # 正值组(navy)直接映射原始值,对应左Y轴 geom_point(aes(x = decile_navy, y = coef_navy, color = 'navy')) + # 负值组(maroon)转换到主Y轴坐标系:保证0值对应绘图底部,最小负值对应绘图顶部 geom_point(aes(x = decile_maroon, y = (coef_maroon + max_abs_maroon) * scl, color = 'maroon')) + labs(x = "Group", y = "Navy组系数", color = "分组") + scale_color_manual(values = c('maroon' = 'maroon', 'navy' = 'navy')) + scale_y_continuous( # 左Y轴设置:顶部为0,底部为正值组最大值,完全匹配需求 limits = c(max_navy, 0), # 右Y轴转换:将主Y轴值反向映射回原始负值范围,实现底部为0、顶部为最大负值 sec.axis = sec_axis(~ (.x / scl) - max_abs_maroon, name = "Maroon组系数") )
逻辑说明
- 左Y轴通过
limits = c(max_navy, 0)直接实现0值位于轴顶部,正值从顶到底递增,匹配正值组数据范围 - 负值组做线性偏移映射:把取值范围
[-1500, 0]平移到[0, 1500]后乘以缩放因子,刚好匹配主Y轴的[0, 0.02]范围,保证负值组的0值落在绘图最底部,-1500落在绘图最顶部 - 次轴通过逆转换把主Y轴坐标映射回原始负值范围,刚好实现右Y轴底部为0、顶部为-1500的需求,完全符合sec_axis仅支持线性转换的限制
如果需要调整轴标签的显示格式,可以通过scale_y_continuous的labels参数自定义,比如用scales::label_number()控制小数位数。
内容的提问来源于stack exchange,提问作者JRR
相关产品推荐
相关产品推荐

