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

如何在ggplot2中用双Y轴正确可视化不同尺度的双数据集散点图

ggplot2双Y轴可视化:解决尺度差异问题

问题根源

你的代码未对第二个数据集的Y值做尺度转换,直接使用sec_axis(~1*.)意味着次轴与主轴刻度范围完全一致,但total_catch(正数,几十到几百)和Sv_log(负数,-70到-58)的尺度完全不重叠,导致Sv_log的点被压缩到轴底部几乎不可见。

核心解法

ggplot2的双Y轴本质是将第二个数据集的Y值线性映射到第一个轴的尺度区间,再通过sec_axis定义逆变换,让右侧轴显示原始数据的真实刻度。具体步骤如下:

1. 计算转换系数

先确定两个数据集Y值的极值,构建线性转换公式:转换后值 = a * 原始值 + b,其中:

  • a 是尺度比例系数,由两个数据集的范围差计算得到
  • b 是偏移量,确保转换后的值落在主Y轴范围内
# 提取df1的Sv_log极值
sv_range <- range(df1$Sv_log)
sv_min <- sv_range[1]
sv_max <- sv_range[2]

# 提取df2的total_catch极值(去重避免重复值干扰)
catch_range <- range(unique(df2$total_catch))
catch_min <- catch_range[1]
catch_max <- catch_range[2]

# 计算线性转换参数
a <- (sv_max - sv_min) / (catch_max - catch_min)
b <- sv_min - a * catch_min

2. 绘制双轴散点图

对total_catch应用转换后的值绘图,同时在sec_axis中使用逆转换~(. - b)/a还原原始渔获量刻度:

library(ggplot2)

ggplot(df1, aes(x = date_column, y = Sv_log)) +
  # 声学反向散射数据(主Y轴)
  geom_point(color = "#1f77b4", size = 2.5) +
  # 总渔获量数据(转换后适配主Y轴)
  geom_point(data = df2, aes(x = date_column, y = a * total_catch + b), 
             color = "#ff7f0e", size = 2.5) +
  # 定义双Y轴
  scale_y_continuous(
    name = "声学反向散射 (Sv, 分贝)",
    sec.axis = sec_axis(
      trans = ~ (. - b)/a,
      name = "总渔获量 (kg)"
    )
  ) +
  labs(x = "日期") +
  theme_bw() +
  # 颜色区分轴标题与刻度,提升可读性
  theme(
    axis.title.y = element_text(color = "#1f77b4", size = 12),
    axis.title.y.right = element_text(color = "#ff7f0e", size = 12),
    axis.text.y = element_text(color = "#1f77b4"),
    axis.text.y.right = element_text(color = "#ff7f0e")
  )

3. 示例数据说明

你的示例df2中所有记录的date_column均为同一日期(2021-03-06),而df1的日期集中在2020-12-13至2020-12-23,因此绘图时两个数据集的点会分布在X轴的不同区段。如果实际数据是同一时间序列,点会对应对齐显示。

关键提示

  • 线性转换必须基于数据集的实际极值,确保转换后的数据完全落在主Y轴的可见范围内
  • 用不同颜色区分两个数据集及其对应轴,避免读者混淆
  • 尽管双Y轴在你的场景中有合理性,但需在可视化中明确标注转换关系,降低误解风险

内容的提问来源于stack exchange,提问作者Jackson A Swan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:57:02