diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml
index 129542db0..38eef4aba 100644
--- a/.github/workflows/pkgdown.yaml
+++ b/.github/workflows/pkgdown.yaml
@@ -57,12 +57,17 @@ jobs:
any::gridExtra
local::.
needs: website
- - name: Setup Micromamba
- uses: mamba-org/setup-micromamba@v1
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v6
with:
- environment-file: environment.yml
- cache-environment: false
- cache-downloads: false
+ python-version: ${{ matrix.python-version }}
+ cache: "pip"
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ run: |
+ python -m pip install --upgrade pip
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Create public directory
run: |
mkdir public
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7494678a0..565ddcb1d 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -53,16 +53,13 @@ build-image:
- name: ${DEVOPS_REGISTRY}usgs/docker:29-dind
alias: docker
script:
- - echo ${CI_REGISTRY_PASSWORD} | docker login -u ${CI_REGISTRY_USER} --password-stdin $CI_REGISTRY
+ - echo "${CI_REGISTRY_PASSWORD}" | docker login -u "${CI_REGISTRY_USER}" --password-stdin $CI_REGISTRY
- docker pull ${CI_REGISTRY_IMAGE}:latest || true
- - cp *.tar.gz docker/
- - cd docker
- - docker build
- -t ${CI_REGISTRY_IMAGE}:latest
- .
+ - docker build --cache-from ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:latest -t ${CI_REGISTRY_IMAGE}:BUILD_${CI_COMMIT_SHORT_SHA} -f docker/Dockerfile .
+ # If this is building a git tag, also push the corresponding docker tag
+ - if [ -n "${CI_COMMIT_TAG}" ]; then docker tag "${CI_REGISTRY_IMAGE}:BUILD_${CI_COMMIT_SHORT_SHA}" "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"; fi
- docker push --all-tags ${CI_REGISTRY_IMAGE}
- artifacts:
- expire_in: 45 minutes
+
buildcheck:
image: ${CI_REGISTRY_IMAGE}:latest
@@ -135,11 +132,11 @@ longtest:
pages:
image: ${CI_REGISTRY_IMAGE}:latest
stage: end
- before_script:
- - conda env create -n dataretrieval -f environment.yml
dependencies:
- build-image
- buildcheck
+ variables:
+ RETICULATE_PYTHON: /usr/bin/python3
script:
- |
Rscript -e '
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d8997e5c7..a7e3f345f 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,54 +1,60 @@
FROM code.chs.usgs.gov:5001/ctek/docker/r-lang/r-base:4.6
-# Change the name of this environment to something which pleases you, if you
-# so please. But the name will not be relevant for most cases, as reticulate
-# will be pointed to the environment no matter what it is named.
-ARG CONDA_ENVIRONMENT_NAME=dataretrieval
-
-RUN apt-get update \
- && apt-get install -y --no-install-recommends \
- wget \
+# System dependencies
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ python3 \
+ python3-pip \
+ python3-dev \
+ # These might already come with r-cran-sf binary, commenting out for now:
+ # libgdal-dev \
+ # libgeos-dev \
+ # libproj-dev \
&& rm -rf /var/lib/apt/lists/*
-
-ENV CONDA_DIR="/root/conda"
-ENV PATH=$CONDA_DIR/bin:$PATH
-RUN wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" && \
- bash Miniforge3.sh -b -p "${HOME}/conda" && \
- rm Miniforge3.sh
+# Python dependencies
+RUN pip3 install --no-cache-dir --break-system-packages \
+ dataretrieval \
+ matplotlib \
+ geopandas \
+ numpy \
+ pandas \
+ scipy \
+ folium>=0.12 \
+ mapclassify \
+ python-dateutil \
+ seaborn \
+ requests
-# Necessary R libraries
-RUN apt-get update -qq && apt-get -y --no-install-recommends install \
- r-cran-rcmdcheck \
- r-cran-testthat \
- r-cran-covr \
- r-cran-reticulate \
- r-cran-curl \
- r-cran-lubridate \
- r-cran-xml2 \
- r-cran-httr2 \
- r-cran-whisker \
- r-cran-dplyr \
- r-cran-sf \
- r-cran-data.table \
- r-cran-jsonlite \
- r-cran-readr \
- r-cran-knitr \
- r-cran-rmarkdown \
- r-cran-dt \
- r-cran-leaflet \
- r-cran-readxl \
- r-cran-pkgdown \
- r-cran-ggplot2 \
- r-cran-tidyr \
- r-cran-purrr \
- && rm -rf /var/lib/apt/lists/*
+# R dependencies
+RUN apt-get update -qq && apt-get install -y --no-install-recommends \
+ r-cran-reticulate \
+ r-cran-curl \
+ r-cran-lubridate \
+ r-cran-xml2 \
+ r-cran-httr2 \
+ r-cran-dplyr \
+ r-cran-sf \
+ r-cran-ggplot2 \
+ r-cran-tidyr \
+ r-cran-purrr \
+ r-cran-jsonlite \
+ r-cran-knitr \
+ r-cran-rmarkdown \
+ r-cran-leaflet \
+ r-cran-data.table \
+ r-cran-readr \
+ r-cran-rcmdcheck \
+ r-cran-testthat \
+ r-cran-pkgdown \
+ r-cran-covr \
+ r-cran-readxl \
+ r-cran-dt \
+ && rm -rf /var/lib/apt/lists/*
-ENV RETICULATE_PYTHON=/root/conda/envs/${CONDA_ENVIRONMENT_NAME}/bin/python
+ENV RETICULATE_PYTHON=/usr/bin/python3
COPY *.tar.gz /tmp/pkg.tar.gz
-
RUN set -eux; \
- R CMD INSTALL /tmp/pkg.tar.gz && \
- Rscript -e "library(dataRetrieval)" && \
- rm -f /tmp/*.tar.gz
+ R CMD INSTALL /tmp/pkg.tar.gz && \
+ Rscript -e "library(dataRetrieval)" && \
+ rm -f /tmp/*.tar.gz
diff --git a/environment.yml b/environment.yml
index 057a1989d..b3b6e3e34 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,8 +1,14 @@
name: dataretrieval
channels:
- conda-forge
+ - defaults
dependencies:
+ - python>=3.10
+ - pip
- dataretrieval
- - matplotlib
+ - matplotlib-base
- geopandas
+ - pyqt
+ - folium>=0.12
+ - mapclassify
prefix: /home/user/miniforge3/envs/dataretrieval
diff --git a/requirements.txt b/requirements.txt
index eb5711775..6e72580fb 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,17 +1,7 @@
-numpy<2
-pandas==2.*
-geopandas==1.1.2
-scipy
-python-dateutil
-requests
-requests-mock
-coverage
-pytest
-flake8
-sphinx
-sphinx-rtd-theme
-ipython
-ipykernel
-nbsphinx
-nbsphinx_link
+dataretrieval
matplotlib
+geopandas
+folium
+mapclassify
+seaborn
+
diff --git a/tutorials/basic_slides_deck.qmd b/tutorials/basic_slides_deck.qmd
index e814e022e..8454907df 100644
--- a/tutorials/basic_slides_deck.qmd
+++ b/tutorials/basic_slides_deck.qmd
@@ -11,7 +11,7 @@ format:
footer:
preview-links: auto
title-slide-attributes:
- data-background-image: hex_logo.png
+ data-background-image: combo_hex.png
data-background-size: 15%
data-background-position: 2% 2%
editor: source
@@ -33,11 +33,20 @@ params:
library(ggplot2)
library(dplyr)
library(reticulate)
+
py_require("dataretrieval")
py_require("panda")
py_require("matplotlib")
+py_require("seaborn")
+py_require("geopandas")
+py_require("folium")
+py_require("mapclassify")
options(dplyr.summarise.inform = FALSE)
+theme_set(theme_bw(base_size = 20))
+update_geom_defaults("point", list(size = 3, color = "steelblue"))
+options(ggplot2.discrete.colour = "viridis")
+
evaluate_python <- params$run_python
dt_me <- function(
@@ -72,100 +81,18 @@ dt_me <- function(
```
-## Introduction {background-image="images/hex_logo.png" background-size="15%" background-position="90% 90%" }
-
-In this ~90 minute introduction, the goal is:
-
-- Introduce the modern `dataRetrieval` workflows.
-
-- The intended audience is someone:
-
- - New to `dataRetrieval`
-
- - Has some R experience
-
-::: footer
-
-:::
-
-
-## RStudio Orientation
-
-By default will look like:
-
-
-
-## RStudio Appearances
-
-Go to Tools -> Global Options -> Appearances to change style.
-
-
-
-## RStudio Orientation {.smaller}
-
-:::: {.columns}
-
-::: {.column width="30%"}
-
-1. Create scripts.
-
-2. See code run.
-
-3. See what variables are loaded
-
- - Click on a data frame to View
-
-4. Plots and more
-
-:::
-
-::: {.column width="70%"}
-
-
-:::
-
-::::
-
-::: footer
-
-:::
-
-
-## dataRetrieval: R-package for US water data {.smaller}
-
-:::: {.columns}
-
-::: {.column width="50%"}
-
-**USGS Water Data APIs * **
-
-- Surface water levels
-
-- Groundwater levels
-
-- Site metadata
-
-- Peak flows
-
-- Rating curves
+## Introduction {background-image="combo_flip.png" background-size="25%" background-position="95% 90%" }
-- Discrete water-quality data
+The goal of these slides are to:
-:::
+- Introduce the modern USGS water data concepts
-::: {.column width="50%"}
+- Introduce basic `dataretrieval` workflows (R and Python)
-**Water Quality Portal (WQP) Data**
+- Introduce additional topics that often come up
-- Discrete water-quality data
-
-- USGS and non-USGS data
-
-:::
-
-::::
-## Installation
+## Software Installation
::: {.panel-tabset}
@@ -188,8 +115,6 @@ library(dataRetrieval)
### Python
-Whether you are a user or developer we recommend installing `dataretrieval` in a virtual environment. This can be done using something like virtualenv or conda.
-
```{bash}
#| echo: true
#| eval: false
@@ -218,27 +143,15 @@ from dataretrieval import waterdata
:::
-## dataRetrieval: External Documentation
-
-{width="1000" height="500"}
-
-::: footer
-
-:::
-
-## dataRetrieval: External Documentation
-
-{width="1000" height="500"}
+## External Documentation
-::: footer
-
-:::
+- R package:
-## dataRetrieval: External Documentation
+- Python package:
-{width="1000" height="500"}
+- WDFN Blog:
-## Documentation within R: function help pages {.smaller}
+## Internal Documentation {.smaller}
::: {.panel-tabset}
@@ -299,62 +212,193 @@ help(waterdata.get_daily)
:::
-## Exercise 1: Orientation {.smaller}
+## USGS Water Data Concepts {.smaller}
-::: {.panel-tabset}
+:::: {.columns}
-### Challenge
+::: {.column width="50%"}
+**USGS Water Data APIs**
-1. Open RStudio
+- Continuous (e.g. 15-minute sensor data)
+
+- Daily (e.g. mean from continuous)
+
+- Monitoring Location Information
-2. Install `dataRetrieval`, `dplyr`, `ggplot2`, and `data.table` (if they are not already installed).
+- Time Series Information
-3. Load `dataRetrieval`
+- Latest Daily/Continuous
-4. Open the help file for the function `read_waterdata_daily`
+- Field Measurements
+
+:::
+
+::: {.column width="50%"}
+**USGS Water Data APIs**
+
+- Peak Flows
+
+- Rating Curves
+
+- Discrete Water-Quality
+
+**Water Quality Portal (WQP) Data**
+
+- Discrete water-quality data (USGS & others)
+
+:::
+
+::::
+
+::: {.callout-important}
+## Each of these is has a different:
+
+* API endpoint
+* `dataRetrieval` function
+* Output format
+:::
+
+
+::: footer
+
+:::
+
+## USGS Basic Retrievals {.smaller}
+
+The USGS uses various codes for basic retrievals. These codes can have leading zeros, therefore they need to be a character surrounded in quotes ("00060").
+
+* Site ID (often 8 or 15-digits)
+* Parameter Code (5 digits)
+ + Full list: `read_metadata("parameter-codes")`
+* Statistic Code (for daily values)
+ + Full list: `read_metadata("statistic-codes")`
+
+## USGS Basic Retrievals Parameter and Statistic Codes
+
+Here are some examples of a few common codes:
+
+
+```{r echo=FALSE, eval=TRUE}
+library(knitr)
+
+df <- data.frame(
+ pCode = c("00060", "00065", "00010", "00400"),
+ shName = c("Discharge", "Gage Height", "Temperature", "pH")
+)
+
+names(df) <- c("Parameter Code", "Short Name")
+
+df2 <- data.frame(
+ pCode = c("00001", "00002", "00003", "00008"),
+ shName = c("Maximum", "Minimum", "Mean", "Median")
+)
+
+names(df2) <- c("Statistic Code", "Short Name")
+
+knitr::kable(list(df, df2))
+```
-5. Navigate to and find the list of function help files and explore some articles in "Additional Articles"
+## `dataRetrieval` can help!
+
+::: {.panel-tabset}
+### R
-### Solution:
+```{r}
+#| eval: false
+parameter_codes <- read_waterdata_metadata("parameter-codes")
+statistic_codes <- read_waterdata_metadata("statistic-codes")
+# Others:
+agency_codes <- read_waterdata_metadata("agency-codes")
+aquifer_codes <- read_waterdata_metadata("aquifer-codes")
+aquifer_types <- read_waterdata_metadata("aquifer-types")
+coordinate_datum_codes <- read_waterdata_metadata("coordinate-datum-codes")
+huc_codes <- read_waterdata_metadata("hydrologic-unit-codes")
+national_aquifer_codes <- read_waterdata_metadata("national-aquifer-codes")
+reliability_codes <- read_waterdata_metadata("reliability-codes")
+site_types <- read_waterdata_metadata("site-types")
+topographic_codes <- read_waterdata_metadata("topographic-codes")
+time_zone_codes <- read_waterdata_metadata("time-zone-codes")
+counties <- read_waterdata_metadata("counties")
+states <- read_waterdata_metadata("states")
+```
+### Python
-```{r fig.height=7}
+```{python}
#| eval: false
-install.packages(c("dataRetrieval", "dplyr", "ggplot2", "data.table"))
-library(dataRetrieval)
-?read_waterdata_daily
+parameter_codes = waterdata.get_reference_table("parameter-codes")
+statistic_codes = waterdata.get_reference_table("statistic-codes")
+# Others:
+agency_codes = waterdata.get_reference_table("agency-codes")
+aquifer_codes = waterdata.get_reference_table("aquifer-codes")
+aquifer_types = waterdata.get_reference_table("aquifer-types")
+coordinate_datum_codes = waterdata.get_reference_table("coordinate-datum-codes")
+huc_codes = waterdata.get_reference_table("hydrologic-unit-codes")
+national_aquifer_codes = waterdata.get_reference_table("national-aquifer-codes")
+reliability_codes = waterdata.get_reference_table("reliability-codes")
+site_types = waterdata.get_reference_tablea("site-types")
+topographic_codes = waterdata.get_reference_table("topographic-codes")
+time_zone_codes = waterdata.get_reference_table("time-zone-codes")
+counties = waterdata.get_reference_table("counties")
+states = waterdata.get_reference_table("states")
```
+::: {style="font-size: 50%;"}
+Each function returns a Tuple, containing a dataframe and a Metadata class.
+:::
+
:::
::: footer
:::
-## dataRetrieval Updates {background-image="images/hex_logo.png" background-size="15%" background-position="85% 80%" }
-Are you a seasoned `dataRetrieval` user?
-Here are resources for recent major changes:
+## Exercise 1: Orientation {.smaller}
+
+::: {.panel-tabset}
+
+### Challenge
+
+1. Open your preferred IDE (RStudio, VSCode, PyCharm, etc) or Jupyter notebook
+
+2. R: Install `dataRetrieval`, `ggplot2`, `dplyr`, `leaflet` (if you haven't already)
+
+2. Python: Install `dataretrieval`, `matplotlib`, `geopandas`, `folium`, `seaborn` (if you haven't already)
+
+3. Load `dataRetrieval` (R) / waterdata module in `dataretrieval` (Python)
+
+4. Open the help file for the function `read_waterdata_daily`
-* [Changes to dataRetrieval](https://doi-usgs.github.io/dataRetrieval/articles/changes_slides.html)
-* [Water Data API Introduction](https://doi-usgs.github.io/dataRetrieval/articles/read_waterdata_functions.html)
+### R
-* [Samples Data Introduction](https://doi-usgs.github.io/dataRetrieval/articles/samples_data.html)
+```{r}
+#| eval: false
+install.packages(c("dataRetrieval", "ggplot2", "leaflet", "dplyr"))
+library(dataRetrieval)
+?read_waterdata_daily
+```
-## What's New? {.smaller}
+### Python
-There's been a lot of changes to `dataRetrieval` over the past year. If you'd like to see an overview of those changes, visit: [Changes to dataRetrieval](https://doi-usgs.github.io/dataRetrieval/articles/changes_slides.html)
+```{bash}
+#| echo: true
+#| eval: false
+pip install dataretrieval matplotlib geopandas folium seaborn
+```
-Biggest changes:
-* NWIS servers will be shut down, so all `readNWIS` functions will eventually stop working
+```{python}
+#| eval: false
+from dataretrieval import waterdata
-* `read_waterdata` functions are modern and should be used when possible
+help(waterdata.get_daily)
+```
-* The "USGS Water Data APIs" are the new home for USGS data
+:::
::: footer
@@ -377,18 +421,11 @@ Biggest changes:
1. Request a USGS Water Data API Token:
-2. Save it in a safe place (KeePass or other password management tool)
-
-3. Add it to your .Renviorn file as API_USGS_PAT.
+2. Save it in a safe place (KeyPass or other password management tool)
-4. Restart R
-
-5. Check that it worked by running (you should see your token printed in the Console):
+3. Add it as environment variable
-```{r}
-#| eval: false
-Sys.getenv("API_USGS_PAT")
-```
+4. Restart
See next slide for a demonstration.
@@ -396,9 +433,13 @@ See next slide for a demonstration.
:::
-## USGS Water Data API Token: Example {.smaller}
+## Water Data API Token: Example {.smaller}
-My favorite method to do add your token to .Renviron is to use the `usethis` package. Let's pretend the token sent you was "abc123":
+Let's pretend the token sent you was "abc123"
+
+::: {.panel-tabset}
+
+### R
1. Run in R:
```{r}
@@ -409,209 +450,124 @@ usethis::edit_r_environ()
2. Add this line to the file that opens up:
-```{r}
-#| eval: false
+```
API_USGS_PAT = "abc123"
```
-3. Save that file using the save button
+3. Save that file
4. Restart R/RStudio.
-5. Run after restarting R:
+5. Check that it worked by running (you should see your token printed in the Console):
```{r}
#| eval: false
Sys.getenv("API_USGS_PAT")
```
-## USGS Water Data API Token: Example {.smaller .nostretch}
-
-{width="50%"}
-
-After save and restart, check that it worked by running:
+::: {.callout-note collapse="true"}
+Your .Renviorn file should never be pushed to a public repository.
+:::
-```{r}
-#| eval: false
-Sys.getenv("API_USGS_PAT")
-```
+### Python: Project
-::: footer
+1. Create a file in your working directory .env
-:::
+2. Add this line to the .env file:
-## USGS Basic Retrievals {.smaller}
+```
+API_USGS_PAT = "abc123"
+```
+4. Restart your python session
-The USGS uses various codes for basic retrievals. These codes can have leading zeros, therefore they need to be a character surrounded in quotes ("00060").
+5. Check that it worked by running (you should see your token printed in the Console):
-* Site ID (often 8 or 15-digits)
-* Parameter Code (5 digits)
- + Full list: `read_waterdata_parameter_codes()`
-* Statistic Code (for daily values)
- + Full list: `read_metadata("statistic-codes")`
+```{python}
+#| echo: true
+#| eval: false
+import os
+os.getenv("API_USGS_PAT")
+'abc123'
+```
-## USGS Basic Retrievals Parameter and Statistic Codes
+::: {.callout-note collapse="true"}
+Your .env file should never be pushed to a public repository.
+:::
-Here are some examples of a few common codes:
+### Python: Conda
+1. Open Miniforge, Anaconda, etc.
-```{r echo=FALSE, eval=TRUE}
-library(knitr)
+2. Activate enviornment
-df <- data.frame(
- pCode = c("00060", "00065", "00010", "00400"),
- shName = c("Discharge", "Gage Height", "Temperature", "pH")
-)
+```{bash}
+#| eval: false
+conda activate flow_bootcamp
+```
-names(df) <- c("Parameter Code", "Short Name")
+3. Add variable:
-df2 <- data.frame(
- pCode = c("00001", "00002", "00003", "00008"),
- shName = c("Maximum", "Minimum", "Mean", "Median")
-)
+```{bash}
+#| eval: false
+conda env config vars set API_USGS_PAT="abc123"
+```
-names(df2) <- c("Statistic Code", "Short Name")
+4. Reactivate enviornment
-knitr::kable(list(df, df2))
+```{bash}
+#| eval: false
+conda activate flow_bootcamp
```
+5. Open your enviornment (for example Jupyter), and test that it's there:
+```{python}
+#| eval: false
+import os
-## Let's Go! {.smaller}
-
-We're going walk through 3 retrievals:
+print(os.getenv("API_USGS_PAT"))
+"abc123"
+```
-* **Workflow 1**: Daily Data
- - Uses the new USGS Water Data API
-
- - Modern data access point going forward
+### Python: Hard-coded
-* **Workflow 2**: Discrete Data
+Within your code, add:
- - Uses new USGS Samples Data
-
- - Modern data access point going forward
-
-* **Workflow 3**: Join Daily and Discrete
+```{python}
+#| eval: false
+import os
+os.environ["API_USGS_PAT"] = "abc123"
+```
-* **Workflow 4**: Continuous Data
-
- - Uses the new USGS Water Data API
-
- - Modern data access point going forward
+This is not ideal because you are hard-coding your personal access token in the script/notebook. You would not want to share this code on a public repository for example.
-* **Workflow 5**: Join Continuous and Discrete
+:::
::: footer
:::
-## Workflow 1: Daily data for known site {.smaller}
+## Water Data APIs: Initial Tips
-Let's pull daily mean discharge data for site "USGS-0940550", getting all the data from the last year.
+Use your "tab" key!
::: {.panel-tabset}
### R
-```{r}
-#| message: true
-library(dataRetrieval)
-site <- "USGS-09405500"
-pcode <- "00060" # Discharge
-stat_cd <- "00003" # Mean
-
-df <- read_waterdata_daily(
- monitoring_location_id = site,
- parameter_code = pcode,
- statistic_id = stat_cd,
- time = "P365D"
-)
-nrow(df)
-```
+
### Python
-```{python}
-#| eval: !expr evaluate_python
-from dataretrieval import waterdata
+{width="60%"}
-site = "USGS-09405500"
-pcode = "00060" # Discharge
-stat_cd = "00003" # Mean
-df, md = waterdata.get_daily(
- monitoring_location_id=site,
- parameter_code=pcode,
- statistic_id=stat_cd,
- time="P365D",
-)
-
-df.shape[0]
-```
-
-:::
-
-::: footer
-
-:::
-
-## Workflow 1: Look at Daily Data {.smaller}
-
-In RStudio, click on the data frame in the upper right Environment tab to open a Viewer.
-
-```{r}
-#| echo: false
-dt_me(
- df |>
- sf::st_drop_geometry(),
- page_length = 3
-)
-```
-
-::: footer
-
-:::
-
-## Workflow 1: Plot Daily Data
-
-::: {.panel-tabset}
-
-### R
-
-Let's use `ggplot2` to visualize the data.
-
-```{r}
-#| echo: true
-#| output-location: column
-library(ggplot2)
-theme_set(theme_bw(base_size = 24))
-update_geom_defaults("point", list(size = 3, color = "steelblue"))
-options(ggplot2.discrete.colour = "viridis")
-
-ggplot(data = df) +
- geom_point(aes(x = time, y = value, color = approval_status))
-```
+### Jupyter Lab
-### Python
-
-Let's use `matplotlib` to visualize the data.
-
-```{python}
-#| echo: true
-#| output-location: column
-import matplotlib.pyplot as plt
-import pandas as pd
-
-plt.rcParams["font.size"] = 20
-
-levels, categories = pd.factorize(df["approval_status"])
+Shift + Tab:
-fig, ax = plt.subplots()
-scatter = ax.scatter(x=df.time, y=df.value, c=levels)
-fig.legend(scatter.legend_elements()[0], categories, title="Status")
-```
+{width="60%"}
:::
@@ -619,15 +575,9 @@ fig.legend(scatter.legend_elements()[0], categories, title="Status")
:::
-## Water Data API Notes: Argument input
+## Water Data API Notes: Arguments
-Use your "tab" key!
-
-
-
-## Water Data API Notes: Arguments {.smaller}
-
-* When you look at the help file for the new functions, you’ll notice there are lots of possible inputs (arguments).
+* When you look at the help file for the new functions, you’ll notice there are lots of possible inputs parameters.
* You **DO NOT** need to (and should not!) specify **all** of these parameters.
@@ -644,7 +594,7 @@ discharge <- read_waterdata_daily(
::: {.fragment}
-::: {style="font-size: 75%;"}
+::: {style="font-size: 50%;"}
Since no list of sites or bounding box was defined, **ALL** the daily data in **ALL** the country with parameter code "00060" and statistic code "00003" will be returned.
@@ -663,7 +613,7 @@ Since no list of sites or bounding box was defined, **ALL** the daily data in **
::: {.column width="50%"}
-The "time" argument has a few options:
+Time parameters have a few options:
* A single date (or date-time): "2024-10-01" or "2024-10-01T23:20:50Z"
@@ -679,6 +629,10 @@ The "time" argument has a few options:
Here are a bunch of valid inputs:
+::: {.panel-tabset}
+
+### R
+
```{r}
#| code-line-numbers: "1-9|10-11|12-15|16-19"
# Ask for exact times:
@@ -702,215 +656,119 @@ time = "P7D" # past 7 days
time = "PT12H" # past hours
```
-:::
-
-::::
-
-## Workflow 2: Discrete data for known site
-
-Use your "tab" key!
-
-
-
-## Workflow 2: Discrete data for known site {.smaller}
-
-Let's get orthophosphate ("00660") data from the Shenandoah River at Front Royal, VA ("USGS-01631000").
-
-::: {.panel-tabset}
-
-### R
-
-```{r}
-#| message: true
-site <- "USGS-01631000"
-pcode <- "00660"
-
-qw_data <- read_waterdata_samples(
- monitoringLocationIdentifier = site,
- usgsPCode = pcode,
- dataType = "results",
- dataProfile = "basicphyschem"
-)
-ncol(qw_data)
-```
-
### Python
```{python}
-#| eval: !expr evaluate_python
-site = "USGS-01631000"
-pcode = "00660"
-
-qw_data, md_qw = waterdata.get_samples(
- monitoringLocationIdentifier = site,
- usgsPCode = pcode,
- service = "results",
- profile = "basicphyschem",
-)
-
-qw_data.shape[1]
+# Ask for exact times:
+time = "2025-01-01"
+# Ask for specific range
+time = "2025-01-01/2026-01-01"
+# Asking beginning of record to specific end:
+time = "../2024-01-01" # or Date or POSIX
+# Asking specific beginning to end of record:
+time = "2024-01-01/.." # or Date or POSIX
+# Ask for period
+time = "P1M" # past month
+time = "P7D" # past 7 days
+time = "PT12H" # past hours
```
-:::
-
-That's a LOT of columns returned. We won't look at them here, but you can use `View` in RStudio to explore on your own.
-::: footer
+:::
:::
-## USGS Samples Data Notes: Data Types and Profiles
+::::
-* There are 2 arguments that dictate what kind of data is returned
- - "dataType" defines what kind of data comes back
- - "dataProfile" defines what columns from that type come back
+## Let's Go!
-## Data Types and Profiles {.smaller}
+* **Workflow 1**: Find Available Sites
-```{r}
-#| echo: false
-df <- tibble(
- dataType = c(
- "results",
- "locations",
- "activities",
- "projects",
- "organizations"
- ),
- Description = c(
- "Results data and metadata for measures and observations matching your query",
- "Find monitoring locations that have data matching your query",
- "Information about the monitoring activities conducted that produced data",
- "Information on the projects that have results matching your data query",
- "Information about the organizations that have provided data that matches your query"
- ),
- dataProfile = c(
- 'fullphyschem
basicphyschem
fullbio
basicbio
narrow
resultdetectionquantitationlimit
labsampleprep
count',
- 'site
count',
- 'sampact
actmetric
actgroup
ncount',
- 'project
projectmonitoringlocationweight',
- 'organization
count'
- )
-)
+* **Workflow 2**: Find Available Data
-dt_me(df, escape = FALSE, paging = FALSE)
-```
+* Challenge 1
+
+* **Workflow 3**: Get Latest Data
-::: footer
+* **Workflow 4**: Get All Data
-:::
+* Challenge 2
+
+* **Workflow 5**: Discrete Water Quality
-## Workflow 2: Discrete data censoring {.smaller}
+## Workflow 1: Find Available Sites
-Let's pull a few columns out and look at those:
+Let's get all the monitoring locations for Dane County, Wisconsin:
::: {.panel-tabset}
### R
```{r}
-library(dplyr)
-
-qw_data_slim <- qw_data |>
- select(
- Date = Activity_StartDate,
- Result_Measure,
- DL_cond = Result_ResultDetectionCondition,
- DL_val = DetectionLimit_MeasureA,
- DL_type = DetectionLimit_TypeA
- ) |>
- mutate(
- Result = if_else(DL_cond != "", DL_val, Result_Measure),
- Detected = if_else(DL_cond != "", "Not Detected", "Detected")
- ) |>
- arrange(Detected)
+#| message: false
+site_info <- read_waterdata_monitoring_location(
+ state_name = "Wisconsin",
+ county_name = "Dane County"
+)
```
-* What is `|>`? It's a pipe! It says take 'this thing' and put it in 'that thing'. You'll also see `%>%` in code, it is also a pipe - they are basically the same.
-
### Python
```{python}
#| eval: !expr evaluate_python
-import numpy as np
-
-qw_data_slim = (
- qw_data.rename(
- columns={
- "Activity_StartDate": "Date",
- "Result_ResultDetectionCondition": "DL_cond",
- "DetectionLimit_MeasureA": "DL_val",
- "DetectionLimit_TypeA": "DL_type",
- }
- )[["Date", "Result_Measure", "DL_cond", "DL_val", "DL_type"]]
- .assign(
- Result=lambda x: np.where(
- x["DL_cond"].notna(), x["DL_val"], x["Result_Measure"]
- )
- )
- .assign(
- Detected=lambda x: np.where(x["DL_cond"].notna(), "Not Detected", "Detected")
- )
- .sort_values(by="Detected", ascending=False)
+
+site_info, md = waterdata.get_monitoring_locations(
+ state_name="Wisconsin", county_name="Dane County"
)
```
:::
+
+::: {.callout-note collapse="true"}
+## Note on county names
+`read_waterdata_monitoring_location` requires "County" in the county_name argument. You can check county names using:
+```{r}
+#| eval: false
+counties <- check_waterdata_sample_params(service = "counties")
+```
+:::
+
::: footer
:::
-## Workflow 2: Discrete data censoring information {.smaller}
+## site_info {.smaller .scrollable}
```{r}
#| echo: false
-dt_me(qw_data_slim, page_length = 8, font = "0.7em")
+dt_me(site_info, 5, "0.6em")
```
::: footer
:::
-## Workflow 3: Join Discrete and Daily
-
-* One common workflow is to join discrete data with daily data.
-
-* In this example, we will look at a site that measures both water quality parameters and has daily mean discharge.
-
-* We will use the `dplyr::left_join` to join the 2 data frames by a date.
-
-::: footer
-
-:::
+## site_info_refined {.smaller}
-## Step 1: Get the data {.smaller}
+Now that we've seen the whole data set, maybe we realize in the future we can ask for just stream sites, and we only really need a few of those columns:
::: {.panel-tabset}
### R
```{r}
-site <- "USGS-04183500"
-p_code_dv <- "00060"
-stat_cd <- "00003"
-p_code_qw <- "00665"
-start_date <- "2015-07-03"
-end_date <- "2025-07-03"
-
-qw_data <- read_waterdata_samples(
- monitoringLocationIdentifier = site,
- usgsPCode = p_code_qw,
- activityStartDateLower = start_date,
- activityStartDateUpper = end_date,
- dataProfile = "basicphyschem"
-)
-
-dv_data <- read_waterdata_daily(
- monitoring_location_id = site,
- parameter_code = p_code_dv,
- statistic_id = stat_cd,
- time = c(start_date, end_date)
+#| message: true
+site_info_refined <- read_waterdata_monitoring_location(
+ state_name = "Wisconsin",
+ county_name = "Dane County",
+ site_type = "Stream",
+ properties = c(
+ "monitoring_location_id",
+ "monitoring_location_name",
+ "drainage_area",
+ "geometry"
+ )
)
```
@@ -918,175 +776,204 @@ dv_data <- read_waterdata_daily(
```{python}
#| eval: !expr evaluate_python
-site = "USGS-04183500"
-p_code_dv = "00060"
-stat_cd = "00003"
-p_code_qw = "00665"
-start_date = "2015-07-03"
-end_date = "2025-07-03"
-
-qw_data, md_qw = waterdata.get_samples(
- monitoringLocationIdentifier=site,
- usgsPCode=p_code_qw,
- activityStartDateLower=start_date,
- activityStartDateUpper=end_date,
- profile="basicphyschem",
-)
-
-dv_data, md_dv = waterdata.get_daily(
- monitoring_location_id=site,
- parameter_code=p_code_dv,
- statistic_id=stat_cd,
- time=(start_date + "/" + end_date),
+site_info_refined, md = waterdata.get_monitoring_locations(
+ state_name="Wisconsin",
+ county_name="Dane County",
+ site_type="Stream",
+ properties=[
+ "monitoring_location_id",
+ "monitoring_location_name",
+ "drainage_area",
+ "geometry",
+ ],
)
```
-
:::
::: footer
:::
-## Step 2: Join
+## Map with geometry {.smaller}
::: {.panel-tabset}
-### R
+### R: ggplot2
```{r}
-little_dv <- dv_data |>
- select(time, Flow = value, monitoring_location_id)
+#| output-location: default
+library(ggplot2)
-qw_data_joined <- qw_data |>
- left_join(little_dv, by = c("Activity_StartDate" = "time"))
+ggplot(data = site_info_refined) +
+ geom_sf()
```
-
-### Python
+### Python: matplotlib
```{python}
#| eval: !expr evaluate_python
-little_dv = dv_data.rename(columns={"value": "Flow"})[
- ["time", "Flow", "monitoring_location_id"]
-]
+import matplotlib.pyplot as plt
+import geopandas as gpd
-qw_data["Activity_StartDate"] = pd.to_datetime(
- qw_data["Activity_StartDate"], format="%Y-%m-%d"
-)
+site_info_refined.plot()
-qw_data_joined = pd.merge(
- qw_data, little_dv, left_on="Activity_StartDate", right_on="time", how="left"
-)
```
:::
-* "Activity_StartDate" (on the left side data frame) and "time" (on the right side data frame) need to be the same type (in this case, both are Date objects).
-
::: footer
:::
-## Step 2: Join (cont.)
-
-* You could join on multiple columns:
+## Interactive Map
::: {.panel-tabset}
### R
```{r}
-#| eval: false
-qw_data <- qw_data |>
- left_join(
- little_dv,
- by = c(
- "Activity_StartDate" = "time",
- "Location_Identifier" = "monitoring_location_id"
- )
- )
+#| eval: true
+#| output-location: slide
+library(leaflet)
+#default leaflet crs:
+leaflet_crs <- "+proj=longlat +datum=WGS84"
+
+leaflet(
+ data = site_info_refined |>
+ sf::st_transform(crs = leaflet_crs)
+) |>
+ addProviderTiles("CartoDB.Positron") |>
+ addCircleMarkers(popup = ~monitoring_location_name, radius = 3, opacity = 1)
```
-See `dplyr` documentation for lots of joining options, but I find `left_join` my "go-to" for straightforward joins.
-
### Python
+If you have `geopandas` installed, the function will return a GeoDataFrame with a geometry column containing the monitoring locations’ coordinates. You can use `gpd.explore()` to view your geometry coordinates on an interactive map.
+
```{python}
-#| eval: !expr evaluate_python
-qw_data = pd.merge(
- qw_data,
- little_dv,
- left_on=["Activity_StartDate", "Location_Identifier"],
- right_on=["time", "monitoring_location_id"],
- how="left",
+#| eval: false
+site_info_refined.set_crs(crs="WGS84").explore(
+ marker_kwds=dict(radius=7),
+ style_kwds=dict(opacity=1, fillOpacity=1),
+ tiles="CartoDB.Positron",
)
```
:::
::: footer
-
+
:::
-## Step 3: Inspect
+## Workflow 2: Find Available Data
-Let's take a quick peak:
+Let's get all the time series in Dane County, WI with daily mean (statistic_id = "00003") discharge (parameter code = "00060") or temperature (parameter code = "00010").
::: {.panel-tabset}
### R
```{r}
-#| output-location: column
-ggplot(data = qw_data_joined) +
- geom_point(aes(x = Flow, y = Result_Measure))
+sites_available <- read_waterdata_combined_meta(
+ state_name = "Wisconsin",
+ county_name = "Dane County",
+ parameter_code = c("00060", "00010"),
+ statistic_id = c("00003")
+)
```
### Python
```{python}
-#| eval: !expr evaluate_python
-#| output-location: column
-plt.figure()
-plt.scatter(x=qw_data_joined.Flow, y=qw_data_joined.Result_Measure)
-```
+sites_available, md = waterdata.get_combined_metadata(
+ state_name = "Wisconsin",
+ county_name = "Dane County",
+ parameter_code = ["00060", "00010"],
+ statistic_id = "00003"
+)
+```
:::
-## Exercise 2: Joins {.smaller}
+## sites_available {.smaller .scrollable}
+
+Selecting just a few columns:
+
+```{r}
+#| echo: false
+dt_me(
+ sites_available |>
+ sf::st_drop_geometry() |>
+ filter(!is.na(begin)) |> # public, but "grade" set to unusable
+ select(monitoring_location_id, parameter_name, parameter_code, begin, end),
+ 6,
+ "0.7em"
+)
+```
+
+## Challenge 1 {.smaller}
::: {.panel-tabset}
-### Challenge
+### Problem Statement
-`dplyr` comes with some data sets. To look at them run:
+1. How many USGS stream sites are within Tuscaloosa County, Alabama?
-```{r}
-library(dplyr)
-band_members <- band_members
-band_instruments <- band_instruments
-```
+2. What are the unique parameter_names that come back from USGS sites in Tuscaloosa County, Alabama?
-1. Run that code and view the 2 data frames to see what they look like.
+3. What site has the longest period of record for daily mean discharge?
-2. Join the instruments to the "band_members" by name.
+4. Bonus: Create an interactive map of all sites that measure gage height.
-3. Join the members to the "band_instruments" by name.
+The amount you get done during this break will highly depend on the extent of your coding background. Use this time to explore dataretrieval functions and outputs.
-### Solution:
+### Solution
+When these slides were generated on `{r} Sys.Date()`, the results were:
```{r}
-band_members |>
- left_join(band_instruments, by = "name")
-
-band_instruments |>
- left_join(band_members, by = "name")
+#| message: false
+#| echo: false
+library(dplyr)
+cat("1. ")
+tus <- read_waterdata_combined_meta(
+ state_name = "Alabama",
+ county_name = "Tuscaloosa County",
+ site_type = "Stream"
+)
+tus |>
+ filter(parameter_name == "Gage height") |>
+ select(monitoring_location_id) |>
+ distinct() |>
+ pull() |>
+ length()
+
+cat("2. ")
+unique(tus$parameter_name)
+
+cat("3. ")
+tus_summary <- tus |>
+ filter(parameter_name == "Discharge", data_type == "Daily values") |>
+ mutate(por = end - begin) |>
+ arrange(desc(por))
+tus_summary$monitoring_location_name[1]
+tus_summary$begin[1]
+tus_summary$end[1]
```
+### Bonus
+```{r}
+#| echo: false
+leaflet(
+ data = tus_summary |>
+ sf::st_transform(crs = leaflet_crs)
+) |>
+ addProviderTiles("CartoDB.Positron") |>
+ addCircleMarkers(popup = ~monitoring_location_name, radius = 3, opacity = 1)
+```
:::
@@ -1094,325 +981,317 @@ band_instruments |>
:::
-## Workflow 4: Continuous data for known site
+## Workflow 3: Get Latest Data {.smaller}
-* Continuous data is the high-frequency sensor data.
-
-* We'll look at Suisun Bay a Van Sickle Island NR Pittsburg CA ("USGS-11455508"), with parameter code "99133" which is Nitrate plus Nitrite.
-
-## Workflow 4: Continuous data for known site {.smaller}
+Let's get the daily discharge measurements in Dane County, WI (parameter code = "00060") that has measured data within the last 14 days.
::: {.panel-tabset}
### R
-:::: {.columns}
-
-::: {.column width="65%"}
-
```{r}
-#| eval: false
-site_id <- "USGS-11455508"
-p_code_rt <- "99133"
-start_date <- "2024-01-01"
-end_date <- "2024-06-01"
-
-continuous_data <- read_waterdata_continuous(
- monitoring_location_id = site_id,
- parameter_code = p_code_rt,
- time = c(start_date, end_date)
+latest_sites <- read_waterdata_combined_meta(
+ state_name = "Wisconsin",
+ county_name = "Dane County",
+ parameter_code = c("00060"),
+ last_modified = "P14D",
+ data_type = "Continuous values"
)
-names(continuous_data)
-```
-
-:::
-::: {.column width="35%"}
-
-```{r}
-#| results: markup
-#| echo: false
-options(width = 30)
-site_id <- "USGS-11455508"
-p_code_rt <- "99133"
-start_date <- "2024-01-01"
-end_date <- "2024-06-01"
-
-continuous_data <- read_waterdata_continuous(
- monitoring_location_id = site_id,
- parameter_code = p_code_rt,
- time = c(start_date, end_date)
+latest_discharge <- read_waterdata_latest_continuous(
+ monitoring_location_id = latest_sites$monitoring_location_id,
+ parameter_code = "00060"
)
-names(continuous_data)
```
-:::
-
-::::
-
### Python
-:::: {.columns}
-
-::: {.column width="65%"}
-
```{python}
-#| eval: false
-site_id = "USGS-11455508"
-p_code_rt = "99133"
-date_range = "2024-01-01/2024-06-01"
-
-continuous_data, md_cont = waterdata.get_continuous(
- monitoring_location_id=site_id, parameter_code=p_code_rt, time=date_range
+latest_sites, md = waterdata.get_combined_metadata(
+ state_name = "Wisconsin",
+ county_name = "Dane County",
+ parameter_code = "00060",
+ last_modified = "P14D",
+ data_type = "Continuous values"
)
-```
-
-:::
-
-::: {.column width="35%"}
-
-```{python}
-#| eval: !expr evaluate_python
-#| results: markup
-#| echo: false
-pd.set_option("display.width", 30)
-site_id = "USGS-11455508"
-p_code_rt = "99133"
-date_range = "2024-01-01/2024-06-01"
-continuous_data, md_cont = waterdata.get_continuous(
- monitoring_location_id=site_id, parameter_code=p_code_rt, time=date_range
+latest_discharge, md = waterdata.get_latest_continuous(
+ monitoring_location_id = latest_sites.monitoring_location_id,
+ parameter_code = "00060"
)
-continuous_data.columns
```
:::
-::::
+::: footer
:::
-
-## Workflow 4: Inspect
+## Workflow 3: Get Latest Data {.smaller}
::: {.panel-tabset}
### R
```{r}
-#| output-location: column
-ggplot(data = continuous_data) +
- geom_point(aes(x = time, y = value))
+#| eval: false
+pal <- colorNumeric("viridis", latest_discharge$value)
+
+leaflet(
+ data = latest_discharge |>
+ sf::st_transform(crs = leaflet_crs)
+) |>
+ addProviderTiles("CartoDB.Positron") |>
+ addCircleMarkers(
+ popup = paste(
+ latest_discharge$monitoring_location_id,
+ "
",
+ latest_discharge$time,
+ "
",
+ latest_discharge$value,
+ latest_discharge$unit_of_measure
+ ),
+ color = ~ pal(value),
+ radius = 3,
+ opacity = 1
+ ) |>
+ addLegend(
+ pal = pal,
+ position = "bottomleft",
+ title = "Latest Discharge",
+ values = ~value
+ )
```
### Python
```{python}
-#| eval: !expr evaluate_python
-#| output-location: column
-plt.figure()
-plt.scatter(x=continuous_data.time, y=continuous_data.value)
+#| eval: true
+#| output-location: slide
+
+latest_discharge.set_crs(crs="WGS84").explore(
+ marker_kwds=dict(radius=7),
+ style_kwds=dict(opacity=1, fillOpacity=1),
+ tiles="CartoDB.Positron",
+ column="value",
+ cmap="viridis",
+ zoom_start=10,
+)
```
:::
-## Workflow 5: Join Discrete and Continuous
+::: footer
+
+:::
-That same site also measures discrete Nitrate plus Nitrite, which is parameter code "00631". Let's first grab that data:
+
+## Workflow 4: Get All Data
+
+Let's get daily discharge data for the last 3 years from 2 sites:
::: {.panel-tabset}
### R
```{r}
-#| message: true
-discrete_data <- read_waterdata_samples(
- monitoringLocationIdentifier = "USGS-11455508",
- usgsPCode = "00631",
- activityStartDateLower = start_date,
- activityStartDateUpper = end_date,
- dataProfile = "basicphyschem"
+daily <- read_waterdata_daily(
+ monitoring_location_id = c("USGS-05406457", "USGS-05427930"),
+ parameter_code = c("00060"),
+ statistic_id = "00003",
+ time = c("2022-10-01", "2025-10-01")
)
```
### Python
```{python}
-#| eval: !expr evaluate_python
-discrete_data, md_qw = waterdata.get_samples(
- monitoringLocationIdentifier = "USGS-11455508",
- usgsPCode = "00631",
- activityStartDateLower = "2024-01-01",
- activityStartDateUpper = "2024-06-01",
- profile = "basicphyschem"
+df, md = waterdata.get_daily(
+ monitoring_location_id= ["USGS-05406457", "USGS-05427930"],
+ parameter_code="00060",
+ statistic_id="00003",
+ time="2022-10-01/2025-10-01",
)
```
:::
-## Workflow 5: Join Discrete and Continuous
-
-* We now want to join the **closest** continuous sensor time with the discrete sample time.
-
-* This is trickier than joining by exact matches.
-
-* `dplyr` has a way, but it's complicated if you want the absolute closest in either direction
-
-* Another package `data.table` has a slick way to get the closest matches
-
-## Workflow 5: Join Discrete and Continuous
+## Workflow 4: Get All Data: Plot It {.smaller}
::: {.panel-tabset}
### R
```{r}
-#| code-line-numbers: "1|2-3|5-10"
-library(data.table)
-setDT(discrete_data)[, join_date := Activity_StartDateTime]
-setDT(continuous_data)[, join_date := time]
-
-closest_dt <- continuous_data[
- discrete_data,
- on = .(join_date),
- roll = "nearest"
-]
-closest_dt <- data.frame(closest_dt)
+ggplot(data = daily) +
+ geom_line(aes(x = time, y = value, color = approval_status)) +
+ facet_grid(monitoring_location_id ~ ., )
+```
+
+### Python
+
+```{python}
+#| eval: true
+import matplotlib.pyplot as plt
+import pandas as pd
+import seaborn
+
+levels, categories = pd.factorize(df["approval_status"])
+graph = seaborn.FacetGrid(
+ df, row="monitoring_location_id", hue="approval_status", height=3, aspect=5
+)
+graph.map(plt.scatter, "time", "value").add_legend()
```
:::
::: footer
-
+
:::
-## Workflow 5: Inspect
+## Challenge 2
-```{r}
-#| output-location: column
-ggplot(data = closest_dt) +
- geom_point(aes(x = Result_Measure, y = value)) +
- geom_abline() +
- expand_limits(x = 0, y = 0) +
- xlab("Discrete") +
- ylab("Continuous")
-```
+### Problem
+1. Navigate to the National Water Dashboard
-## Data Discovery
+2. Zoom in and explore sections of the map that have generally higher than normal streamflow.
-The process for discovering data is a bit in flux with NWIS retiring. I expect a new process will be introduced soon. For now here are some options.
+3. Zoom in and explore sections of the map that have generally lower than normal streamflow.
-1. `read_waterdata_ts_meta` discovers daily and continuous time series
+4. Pick a USGS site that is interesting to you (maybe you are a kayaker, maybe you fish, maybe it's a local stream, maybe it's in an extreme flood/drought).
-2. `summarize_waterdata_samples` discovers discrete data at specific monitoring locations
+5. Plot the daily mean discharge data for all time for the site you picked.
-The next slides will demo how to use those.
-## Data Discovery: Time Series {.smaller}
+## Workflow 5: Get Discrete Water Quality Data {.smaller}
+
+Let's get orthophosphate ("00660") data from the Shenandoah River at Front Royal, VA ("USGS-01631000").
::: {.panel-tabset}
### R
+
```{r}
-ts_available <- read_waterdata_ts_meta(monitoring_location_id = "USGS-04183500")
+#| message: true
+site <- "USGS-01631000"
+pcode <- "00660"
+
+qw_data <- read_waterdata_samples(
+ monitoringLocationIdentifier = site,
+ usgsPCode = pcode,
+ dataType = "results",
+ dataProfile = "basicphyschem"
+)
+ncol(qw_data)
```
### Python
-
```{python}
-#| eval: false
-ts_avail, ts_me = waterdata.get_time_series_metadata(
- monitoring_location_id="USGS-04183500"
+#| eval: !expr evaluate_python
+site = "USGS-01631000"
+pcode = "00660"
+
+qw_data, md_qw = waterdata.get_samples(
+ monitoringLocationIdentifier = site,
+ usgsPCode = pcode,
+ service = "results",
+ profile = "basicphyschem",
)
+
+qw_data.shape[1]
```
:::
-```{r}
-#| echo: false
-dt_me(
- ts_available |>
- sf::st_drop_geometry() |>
- select(
- parameter_name,
- parameter_code,
- statistic_id,
- begin,
- end,
- computation_identifier
- ),
- page_length = 6
-)
-```
+That's a LOT of columns returned.
::: footer
:::
-## Data Discovery: Discrete {.smaller}
+## USGS Samples Data Notes: Data Types and Profiles
::: {.panel-tabset}
### R
-```{r}
-discrete_available <- summarize_waterdata_samples(
- monitoringLocationIdentifier = "USGS-04183500"
-)
-```
-
-
-:::
+* There are 2 arguments that dictate what kind of data is returned
+ - "dataType" defines what kind of data comes back
+ - "dataProfile" defines what columns from that type come back
-```{r}
-#| echo: false
-dt_me(
- discrete_available |>
- select(
- characteristicUserSupplied,
- resultCount,
- activityCount,
- firstActivity,
- mostRecentActivity
- ),
- page_length = 6
-)
-```
+### Python
-::: footer
+* There are 2 parameters that dictate what kind of data is returned
+ - "service" defines what kind of data comes back
+ - "profile" defines what columns from that type come back
:::
-## characteristicUserSupplied {.smaller}
-
-* characteristicUserSupplied can be an input to `read_waterdata_sample`
+## {.smaller}
::: {.panel-tabset}
### R
```{r}
-discrete1 <- read_waterdata_samples(
- characteristicUserSupplied = "Phosphorus as phosphorus, water, unfiltered",
- monitoringLocationIdentifier = "USGS-04183500"
+#| echo: false
+df <- tibble(
+ dataType = c(
+ "results",
+ "locations",
+ "activities",
+ "projects",
+ "organizations"
+ ),
+ Description = c(
+ "Results data and metadata for measures and observations matching your query",
+ "Find monitoring locations that have data matching your query",
+ "Information about the monitoring activities conducted that produced data",
+ "Information on the projects that have results matching your data query",
+ "Information about the organizations that have provided data that matches your query"
+ ),
+ dataProfile = c(
+ 'fullphyschem
basicphyschem
fullbio
basicbio
narrow
resultdetectionquantitationlimit
labsampleprep
count',
+ 'site
count',
+ 'sampact
actmetric
actgroup
ncount',
+ 'project
projectmonitoringlocationweight',
+ 'organization
count'
+ )
)
-nrow(discrete1)
+
+dt_me(df, escape = FALSE, paging = FALSE)
```
### Python
-```{python}
-#| eval: !expr evaluate_python
-discrete1, discrete1_me = waterdata.get_samples(
- characteristicUserSupplied = "Phosphorus as phosphorus, water, unfiltered",
- monitoringLocationIdentifier = "USGS-04183500"
-)
-discrete1.shape[1]
+```{r}
+#| echo: false
+names(df) <- c("service", "Description", "profile")
+
+dt_me(df, escape = FALSE, paging = FALSE)
```
:::
+::: footer
+
+:::
+
+## Data Sources
+
+The examples in these slides got all the data from the Water Data API:
+
+
+
+The `dataretrieval` packages also include functions to access:
+
+* [Water Quality Portal](