Exercise 21: Vizualizing Time Series

ESS 330 - Quantitative Reasoning

library(dataRetrieval)
Warning: package 'dataRetrieval' was built under R version 4.4.3
library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(tidyverse)
Warning: package 'lubridate' was built under R version 4.4.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ readr     2.1.5
✔ ggplot2   3.5.1     ✔ stringr   1.5.1
✔ lubridate 1.9.4     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(ggplot2)
library(lubridate)
library(zoo)
Warning: package 'zoo' was built under R version 4.4.3

Attaching package: 'zoo'

The following objects are masked from 'package:base':

    as.Date, as.Date.numeric
library(tsibble)
Warning: package 'tsibble' was built under R version 4.4.3
Registered S3 method overwritten by 'tsibble':
  method               from 
  as_tibble.grouped_df dplyr

Attaching package: 'tsibble'

The following object is masked from 'package:zoo':

    index

The following object is masked from 'package:lubridate':

    interval

The following objects are masked from 'package:base':

    intersect, setdiff, union
library(plotly)
Warning: package 'plotly' was built under R version 4.4.3

Attaching package: 'plotly'

The following object is masked from 'package:ggplot2':

    last_plot

The following object is masked from 'package:stats':

    filter

The following object is masked from 'package:graphics':

    layout
library(feasts)
Warning: package 'feasts' was built under R version 4.4.3
Loading required package: fabletools
Warning: package 'fabletools' was built under R version 4.4.3
# Bringing in Data
# Timeseries Example
# Cache la Poudre River at Mouth (USGS site 06752260)
poudre_flow <- readNWISdv(siteNumber = "06752260",    # Download data from USGS for site 06752260
                          parameterCd = "00060",      # Parameter code 00060 = discharge in cfs)
                          startDate = "2013-01-01",   # Set the start date
                          endDate = "2023-12-31") |>  # Set the end date
  renameNWISColumns() |>                              # Rename columns to standard names (e.g., "Flow", "Date")
  mutate(Date = yearmonth(Date)) |>                   # Convert daily Date values into a year-month format (e.g., "2023 Jan")
  group_by(Date) |>                                   # Group the data by the new monthly Date
  summarise(Flow = mean(Flow))                       # Calculate the average daily flow for each month
GET:https://waterservices.usgs.gov/nwis/dv/?site=06752260&format=waterml%2C1.1&ParameterCd=00060&StatCd=00003&startDT=2013-01-01&endDT=2023-12-31
# 1. Convert to tsibble
poudre_ts <- poudre_flow %>% 
  as_tsibble(index = Date)

# 2. Plot and animate the time series
ts_plot <- ggplot(poudre_ts, aes(x = Date, y = Flow)) +
  geom_line(color = "steelblue") +
  labs(title = "Poudre River Flow",
       x = "Date",
       y = "Flow (cfs)") +
  theme_minimal()

ggplotly(ts_plot)
# 3. Subseries Plot
subseries_plot <- gg_subseries(poudre_ts, Flow) +
  labs(
    title = "Montly Streamflow: Cache la Poudre River (2013-2023)",
    subtitle = "Each panel show the avg. streamflow (cfs) for a given month over 10 years.",
    x = "Date",
    y = "Average Monthly Flow (cfs)"
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 16),
    plot.subtitle = element_text(size = 12),
    strip.text = element_text(face = "bold"),
    axis.text.x = element_text(angle = 90, hjust = 1, vjust = -1),
  )

ggplotly(subseries_plot)
  1. The subseries in this example represent months, and seasons are defined by the average monthly flow rate. In hydrology and river ecology seasons are really more binary than in human perception. There are wet and dry seasons as well as hot or cold seasons although the latter to a lesser extent.
# 4. Decomposition using STL
decomp <- poudre_ts %>% 
  model(STL(Flow ~ season(window = "periodic"))) %>% 
  components()

autoplot(decomp)

  1. In general the decomposition shows the flow decreasing over time but also becoming more volatile over time, particularly in the wet months. While the base flows do decrease slightly the trend shows a much clearer difference; such a difference may be better reflected in the consistency or stability of the flow reigeme.