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

如何在ggplot2中添加第三个次级Y轴以展示多类水文监测数据?

如何在ggplot2(兼容gganimate)中添加第三个Y轴展示浊度数据

ggplot2的sec_axis()仅支持添加一个次级Y轴,无法直接通过它实现第三个Y轴。但可以通过数据缩放+手动模拟轴元素的方式实现,同时兼容gganimate制作动画。


步骤1:预处理数据,计算浊度的缩放因子

为了让浊度数据适配主Y轴(流量)的显示范围,先计算缩放比例,将浊度值映射到流量的数值区间内:

# 加载所需包
library(lubridate)
library(dplyr)
library(ggplot2)
library(gganimate)
library(dataRetrieval)

# 读取并清洗数据(沿用你的原有代码)
siteNo <- "********"
pCode <- c("00060","63680","00010")
start.date <- "yyyy-mm-dd"
end.date <- "yyyy-mm-dd"
YS <- readNWISuv(siteNumbers = siteNo, parameterCd = pCode, startDate = start.date, endDate = end.date)
YS <- renameNWISColumns(YS)
YS <- YS %>% select(dateTime,Flow_Inst,Turb_Inst, Wtemp_Inst)

# 计算浊度的缩放因子(基于流量和浊度的最大值)
scale_turb <- max(YS$Flow_Inst, na.rm = TRUE) / max(YS$Turb_Inst, na.rm = TRUE)
# 添加缩放后的浊度列
YS <- YS %>% mutate(Turb_scaled = Turb_Inst * scale_turb)

步骤2:修改ggplot代码,添加浊度图层并模拟第三个Y轴

在原有双Y轴代码基础上,添加浊度折线,再通过annotate()和theme()手动绘制第三个Y轴的刻度、标签和标题:

YSHG <- YS %>% ggplot(aes(x = dateTime)) +
  # 流量(主Y轴,蓝色)
  geom_line(aes(y = Flow_Inst, color = "Discharge")) +
  # 水温(缩放后对应第一个次级Y轴,红色)
  geom_line(aes(y = Wtemp_Inst * 3000, color = "Temperature")) +
  # 浊度(缩放后对应模拟的第三个Y轴,绿色)
  geom_line(aes(y = Turb_scaled, color = "Turbidity")) +
  
  # 主Y轴与第一个次级Y轴配置
  scale_y_continuous(
    name = "Discharge (cfs)",
    sec.axis = sec_axis(~ ./3000, name = "Water Temperature (°C)"),
    # 确保Y轴范围覆盖所有缩放后的数据
    limits = c(0, max(c(YS$Flow_Inst, YS$Wtemp_Inst*3000, YS$Turb_scaled), na.rm = TRUE))
  ) +
  
  # 颜色与图例配置
  scale_color_manual(
    values = c("Discharge" = "blue", "Temperature" = "red", "Turbidity" = "green"),
    name = "Parameter"
  ) +
  
  # 主题与轴样式调整
  theme_classic() +
  theme(
    plot.background = element_blank(),
    panel.grid = element_blank(),
    panel.border = element_blank(),
    axis.line.x = element_line(color = "black"),
    # 主Y轴样式
    axis.title.y.left = element_text(color = "blue"),
    axis.line.y.left = element_line(color = "blue"),
    # 第一个次级Y轴样式
    axis.title.y.right = element_text(color = "red", margin = margin(l = 10)),
    axis.line.y.right = element_line(color = "red"),
    # 留出右侧空间放置第三个Y轴
    plot.margin = margin(10, 80, 10, 10)
  ) +
  
  # 手动添加第三个Y轴的刻度线、标签和标题
  annotate("segment", 
           x = max(YS$dateTime), xend = max(YS$dateTime) + hours(6),
           y = seq(0, max(YS$Flow_Inst, na.rm = TRUE), length.out = 5),
           yend = seq(0, max(YS$Flow_Inst, na.rm = TRUE), length.out = 5),
           color = "green") +
  annotate("text", 
           x = max(YS$dateTime) + days(1),
           y = seq(0, max(YS$Flow_Inst, na.rm = TRUE), length.out = 5),
           label = round(seq(0, max(YS$Turb_Inst, na.rm = TRUE), length.out = 5), 1),
           color = "green", hjust = 0) +
  annotate("text", 
           x = max(YS$dateTime) + days(1), y = max(YS$Flow_Inst, na.rm = TRUE)/2,
           label = "Turbidity (NTU)", color = "green", hjust = 0, angle = 90) +
  
  labs(x = "Date", y = "Discharge (CFS)")

步骤3:添加gganimate动画

直接在上述ggplot对象基础上添加动画层,实现时间推进的演示效果:

# 制作时间推进动画
animated_plot <- YSHG +
  transition_time(dateTime) +
  labs(title = "Hydrological Data: {frame_time}") +
  ease_aes("linear")

# 渲染动画(可调整fps和duration参数控制动画速度)
animate(animated_plot, fps = 10, duration = 15)

注意事项

  • 缩放因子需基于全局数据计算,避免动画过程中轴范围波动;
  • 模拟的第三个Y轴是视觉层面的对齐,并非ggplot原生轴,需手动调整刻度位置和标签确保准确性;
  • 如果浊度与流量数值范围差异极大,可改用对数转换调整缩放逻辑,保证数据可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 21:42:46