I'm working with a time series of 15-minute river flow observations collected over a 2-week period, and I'm trying to determine the dateTime of the peaks in river flow during this time. I've tried a number of packages/functions including ggpmisc::stat_peaks()
(example below), pracma::findpeaks()
, and cardidates::peakwindow()
, which claim to identify peaks in a time series, but I haven't been able to achieve realistic results with any of them. Can anyone advise how to identify realistic peaks in a time series using ggpmisc::stat_peaks()
? I'm also open to answers from other packages if ggpmisc
isn't the best option.
library(tidyverse)
library(dataRetrieval)
library(ggpmisc)
# 1. Download time series of river water flow
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)
# 2. See data structure
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
# 3. Visualize time series of river flow over 2-week period
dat %>%
ggplot(aes(x = dateTime, y = flow)) +
geom_line() +
theme_bw()
# 4. Attempt to use stat_peaks to identify peaks in time series
dat %>%
ggplot(aes(x = dateTime, y = flow)) +
geom_line() +
stat_peaks(color = 'red') +
theme_bw()
# 4. Attempt to use stat_peaks to identify peaks in time series
dat %>%
ggplot(aes(x = dateTime, y = flow)) +
geom_line() +
stat_peaks(color = 'red',
strict = TRUE) +
theme_bw()
The ideal output (based on "eye-balling" the peaks) would look something like this:
Created on 2025-03-17 with reprex v2.1.1
cardidates::peakwindow
works fine, you just need to adjust mincut
to detect more or fewer peaks:
ggplot(dat, aes(x = dateTime, y = flow)) +
geom_line() + # geom_point() +
geom_point(
aes(as.POSIXct(x), y),
cardidates::peakwindow(dat$dateTime, dat$flow, mincut = 0.9)$peaks,
color = 'red'
) +
theme_bw()
One reason stat_peaks
struggles is that some of your peaks have duplicated values at the top, and algorithms looking for strict increases and decreases will fail.