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

如何用ggpmisc或其他R包识别水文时间序列的真实峰值?

河流量时间序列峰值识别问题及解决方案

我正在处理一段为期两周、间隔15分钟的河流量观测时间序列,想要确定该时段内河流量峰值对应的dateTime。尝试过ggpmisc::stat_peaks()、pracma::findpeaks()和cardidates::peakwindow()等工具,但均未得到符合人工目视判断的真实峰值结果。以下是问题复现及解决方案:


数据获取与预处理

library(tidyverse)
library(dataRetrieval)
library(ggpmisc)

# 下载河流量时间序列数据
dat <- readNWISuv(siteNumbers = "01576381",
                  parameterCd = "00060",
                  startDate = "2024-04-01",
                  endDate = "2024-04-15",
                  tz = "America/New_York") %>% 
  renameNWISColumns() %>% 
  rename(flow = Flow_Inst) %>% 
  select(dateTime, flow)

# 查看数据结构
head(dat)
#>              dateTime flow
#> 1 2024-04-01 00:00:00 25.0
#> 2 2024-04-01 00:15:00 25.6
#> 3 2024-04-01 00:30:00 25.0
#> 4 2024-04-01 00:45:00 25.6
#> 5 2024-04-01 01:00:00 25.1
#> 6 2024-04-01 01:15:00 25.6

原始时间序列可视化

dat %>% 
  ggplot(aes(x = dateTime, y = flow)) +
  geom_line() +
  theme_bw()

河流量时间序列可视化

stat_peaks的尝试结果

默认参数识别

dat %>% 
  ggplot(aes(x = dateTime, y = flow)) +
  geom_line() +
  stat_peaks(color = 'red') +
  theme_bw()

stat_peaks默认参数识别结果

开启strict参数识别

dat %>% 
  ggplot(aes(x = dateTime, y = flow)) +
  geom_line() +
  stat_peaks(color = 'red',
             strict = TRUE) +
  theme_bw()

stat_peaks开启strict参数识别结果

理想识别结果(人工目视判断)

理想峰值识别结果


解决方案

1. 优化ggpmisc::stat_peaks参数

默认参数会识别所有局部极小值,导致大量高频小峰值。通过设置窗口范围与高度阈值,过滤掉无意义的微小波动:

可视化层面调整

dat %>% 
  ggplot(aes(x = dateTime, y = flow)) +
  geom_line() +
  stat_peaks(color = 'red',
             span = 96, # 窗口半宽,对应24小时(96个15分钟间隔点)
             ignore_threshold = 0.5, # 峰值与窗口内最小值的最小高度差
             strict = TRUE) +
  theme_bw()
  • span:定义判断峰值的滑动窗口半宽,单位为数据点数量。设置为96可过滤日内小波动,聚焦跨日的真实峰值。
  • ignore_threshold:设定峰值必须高于窗口内最小值的阈值,过滤微小起伏。

提取峰值数据

若需直接获取峰值对应的dateTime与流量值,使用底层的ggpmisc::find_peaks函数:

peaks_dat <- dat %>% 
  mutate(is_peak = ggpmisc::find_peaks(flow, span = 96, ignore_threshold = 0.5, strict = TRUE)) %>% 
  filter(is_peak)

print(peaks_dat)

2. 推荐其他工具方案

pracma::findpeaks

该函数支持更灵活的峰值规则定义,比如最小峰值高度、峰值间最小间隔:

library(pracma)

# 提取流量向量
flow_vals <- dat$flow

# 识别峰值:设置最小峰值高度、峰值间最小间隔(96个点=24小时)
peak_info <- findpeaks(flow_vals, minpeakheight = 26, minpeakdistance = 96)

# 提取对应数据
peaks_pracma <- dat[peak_info[, 2], ]

forecast::findPeaks

用法简洁,通过阈值与窗口过滤小峰值:

library(forecast)

# 识别峰值
peak_indices <- findPeaks(flow_vals, threshold = 0.5, span = 96)

# 提取对应数据
peaks_forecast <- dat[peak_indices, ]

核心思路

所有工具的核心逻辑一致:通过定义窗口范围过滤高频波动,通过高度阈值区分真实峰值与噪声。需根据数据的波动特征调整参数,比如窗口大小对应你认为的“真实峰值”时间间隔,高度阈值对应峰值与背景波动的最小差值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 18:35:54