ggplot2中围绕1的镜像(居中)对数轴实现方案问询
自定义镜像坐标轴实现方案
要实现围绕1的镜像轴(大于1用log10变换,小于1用反向平方根变换),核心是自定义ggplot2的坐标轴变换函数,不用修改原始数据,直接对坐标轴映射逻辑做调整。
步骤说明
自定义变换规则:
- 比值>1的部分:保留log10变换,将x映射为
log10(x) - 比值<1的部分:用反向平方根变换,将x映射为
-sqrt(1/x - 1)(负号用于让小于1的数值在1的左侧对称分布) - 比值=1时,映射为0
- 比值>1的部分:保留log10变换,将x映射为
用
scales::new_transformation创建自定义变换,同时定义逆变换(用于从坐标轴位置还原原始比值)、刻度生成和标签格式化逻辑。
完整可复现代码
library(ggplot2) library(scales) library(dplyr) # 自定义镜像变换 mirror_trans <- function() { trans_new( name = "mirror_log_sqrt", transform = function(x) { case_when( x > 1 ~ log10(x), x < 1 ~ -sqrt(1/x - 1), TRUE ~ 0 ) }, inverse = function(x) { case_when( x > 0 ~ 10^x, x < 0 ~ 1/(1 + x^2), TRUE ~ 1 ) }, breaks = function(x) { # 手动设置合理刻度:1附近的精细刻度 + 极值刻度 c(0.001, 0.1, 0.75, 0.88, 0.95, 1, 1.15, 1.3, 2, 2.5, 99) }, format = function(x) { # 保持原始数值的标签显示 as.character(x) } ) } # 示例数据 SampleData <- data.frame(CaseID = letters[1:10], Ratio = c(0.1, 0.95, 1.3, 2, 99, 0.88, 0.001, 1.15, 2.5, 0.75)) # 绘图 SampleData %>% ggplot(aes(x = Ratio, y = CaseID)) + geom_point(size = 2) + geom_vline(xintercept = 1, linetype = "dashed", color = "red") + theme_bw() + scale_x_continuous(trans = mirror_trans(), name = "Ratio (mirror transformed)") + # 自定义刻度标签,避免重叠 theme(axis.text.x = element_text(angle = 45, hjust = 1))
效果说明
- 大于1的数值(如1.15、1.3、2、99)依然用log10变换,保留了极值间的分辨率
- 小于1的数值(如0.75、0.88、0.95、0.1、0.001)通过反向平方根变换,放大了0.75-1之间的差异,解决了log10变换下这部分数值挤在一起的问题
- 所有变换仅作用于坐标轴映射,原始
Ratio数据完全未修改
内容的提问来源于stack exchange,提问作者Leander
相关产品推荐
相关产品推荐

