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

如何用ggplot2绘制左轴log10刻度、右轴线性刻度的双Y轴图?

双Y轴(log10左轴 + 线性右轴)对齐解决方案

要实现左轴log10刻度、右轴线性刻度且两者对齐,核心是将右侧变量的数值范围线性映射到左侧log刻度的数值范围,再通过反向转换生成右轴刻度。以下是完整代码和说明:

library(tidyverse)

# 原始数据框
df <- tibble(
  TIME = 0:19,
  VAL1 = seq(from = 10, to = 2500, length.out = 20),
  VAL2 = seq(from = 1, to = 30, length.out = 20))

# 计算左右轴的范围参数
log_range <- log10(range(df$VAL1))  # 左轴log10后的范围
lin_range <- range(df$VAL2)        # 右轴线性范围

# 定义转换函数:将VAL2映射到左轴log范围
val2_to_log <- function(x) {
  (x - lin_range[1]) / (lin_range[2] - lin_range[1]) * (log_range[2] - log_range[1]) + log_range[1]
}

# 定义反向转换函数:将左轴log值转回VAL2的线性值(用于右轴刻度)
log_to_val2 <- function(x) {
  (x - log_range[1]) / (log_range[2] - log_range[1]) * (lin_range[2] - lin_range[1]) + lin_range[1]
}

# 绘制对齐的双Y轴图
ggplot(df, aes(x = TIME)) +
  # 左轴折线:VAL1,用log10转换后的值绘制
  geom_line(aes(y = log10(VAL1), color = "VAL1"), size = 1) +
  # 右轴折线:VAL2,用转换到log范围的值绘制
  geom_line(aes(y = val2_to_log(VAL2), color = "VAL2"), size = 1) +
  # 设置Y轴:左轴显示原始VAL1的log10刻度,右轴生成对应VAL2的线性刻度
  scale_y_continuous(
    name = "VAL1 (log10)",
    breaks = seq(log_range[1], log_range[2], by = 0.5),
    labels = ~ 10^.x,  # 将log值转回原始数值显示
    sec.axis = sec_axis(
      trans = log_to_val2,
      name = "VAL2 (linear)",
      breaks = seq(lin_range[1], lin_range[2], by = 5)  # 自定义右轴刻度间隔
    )
  ) +
  scale_color_manual(values = c("VAL1" = "#2c3e50", "VAL2" = "#e74c3c")) +
  labs(x = "TIME") +
  theme_minimal() +
  theme(legend.position = "top")

关键说明

  1. 范围映射:通过val2_to_log将VAL2的线性范围拉伸/压缩到VAL1的log10数值范围,保证两条折线的垂直位置在图上对齐。
  2. 反向转换:log_to_val2用于将左轴的log刻度值转换为VAL2的原始线性值,确保右轴刻度与左轴的空间位置一一对应。
  3. 刻度自定义:可以通过调整breaks参数修改左右轴的刻度间隔,适配数据分布。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 15:05:03