Example Plots

This notebook illustrates the different types of graph you can produce with Hydrofunctions. We have:

  • hydrograph

  • flow duration

  • cycleplot

  • histogram

We’ll start with the usual imports:

[1]:
import hydrofunctions as hf
import pandas as pd
%matplotlib inline
hf.__version__
pd.__version__
[1]:
'0.24.2'

We’re going to use two datasets in the following examples. The first dataset was collected at two sites along the Shenandoah River.

[2]:
sites = ['01634000', '01632000']  # the first is downstream of the second.
start = '2008-01-01'
end = '2018-01-01'
service = 'dv'
# Request our data.
request = hf.NWIS(sites, service, start, end, file='graphing-1.parquet')
request # Verify that the data request went fine.
Reading data from graphing-1.parquet
[2]:
USGS:01632000: N F SHENANDOAH RIVER AT COOTES STORE, VA
    00010: <Day>  Temperature, water, degrees Celsius
    00060: <Day>  Discharge, cubic feet per second
    00095: <Day>  Specific conductance, water, unfiltered, microsiemens per centimeter at 25 degrees Celsius
USGS:01634000: N F SHENANDOAH RIVER NEAR STRASBURG, VA
    00060: <Day>  Discharge, cubic feet per second
    00095: <2 * Days>  Specific conductance, water, unfiltered, microsiemens per centimeter at 25 degrees Celsius
    00400: <Day>  pH, water, unfiltered, field, standard units
    63680: <Day>  Turbidity, water, unfiltered, monochrome near infra-red LED light, 780-900 nm, detection angle 90 +-2.5 degrees, formazin nephelometric units (FNU)
Start: 2008-01-01 00:00:00+00:00
End:   2018-01-01 00:00:00+00:00

This second dataset is for two years of data collected every five minutes, with five different parameters collected. This request may take a while the first time! After that, Hydrofunctions will automatically access the data from the parquet file.

[3]:
site = '01581752'
request2 = hf.NWIS(site, 'iv', '2016-01-01', '2018-12-31', file='graphing-2.parquet')
request2
Reading data from graphing-2.parquet
[3]:
USGS:01581752: PLUMTREE RUN NEAR BEL AIR, MD
    00010: <5 * Minutes>  Temperature, water, degrees Celsius
    00060: <5 * Minutes>  Discharge, cubic feet per second
    00065: <5 * Minutes>  Gage height, feet
    00095: <5 * Minutes>  Specific conductance, water, unfiltered, microsiemens per centimeter at 25 degrees Celsius
    63680: <5 * Minutes>  Turbidity, water, unfiltered, monochrome near infra-red LED light, 780-900 nm, detection angle 90 +-2.5 degrees, formazin nephelometric units (FNU)
Start: 2016-01-01 05:00:00+00:00
End:   2019-01-01 04:55:00+00:00

Create two nice clean dataframes that we’ll plot with.

[4]:
Q = request.df('q') # Q stands for discharge
T = request2.df('00010') # T stands for water temperature.

Rename the columns to something easier to remember.

[5]:
Q = Q.rename(columns={"USGS:01632000:00060:00003": "Upstream", "USGS:01634000:00060:00003": "Downstream"})
Q.head(2)
[5]:
Upstream Downstream
datetimeUTC
2008-01-01 00:00:00+00:00 112.0 330.0
2008-01-02 00:00:00+00:00 109.0 320.0
[6]:
T = T.rename(columns={"USGS:01581752:00010:00000": "Plumtree"})
T.head(2)
[6]:
Plumtree
datetimeUTC
2016-01-01 05:00:00+00:00 8.7
2016-01-01 05:05:00+00:00 8.7

Plotting a hydrograph

Hydrographs can be produced simply by using the built-in .plot() method of our dataframe.

[7]:
Q.plot()
C:\Users\Marty\Anaconda3\envs\py37hfdev\lib\site-packages\pandas\core\arrays\datetimes.py:1172: UserWarning: Converting to PeriodArray/Index representation will drop timezone information.
  "will drop timezone information.", UserWarning)
[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x1a8d3fcbe48>
../_images/notebooks_Graphing_13_2.png

Plotting a flow duration chart

Flow duration charts are function included in Hydrofunctions. We’ll use the ‘linear’ option to scale the X axis.

[8]:
hf.flow_duration(Q, xscale='linear')
[8]:
(<Figure size 432x288 with 1 Axes>,
 <matplotlib.axes._subplots.AxesSubplot at 0x1a8d41faa90>)
../_images/notebooks_Graphing_15_1.png

Now let’s plot the same data using the default ‘logit’ scale

[9]:
hf.flow_duration(Q, xscale='logit')
[9]:
(<Figure size 432x288 with 1 Axes>,
 <matplotlib.axes._subplots.AxesSubplot at 0x1a8d43d6c88>)
../_images/notebooks_Graphing_17_1.png

Plotting a cycleplot chart

The cycleplot helps to illustrate various natural cycles in your dataset. It plots a single column of data so that the data value is on the Y axis, and time is on the X axis. The time axis is set to show either an annual cycle (shown below), a weekly cycle, or a diurnal cycle (default).

In our example below, the ten years of daily data are plotted over the course of a year, and all of the values within a week are averaged and plotted by week number. The median and mean for each week are shown with lines, while the 20th, 40th, 60th, and 80th percentile are shown with shaded fills.

For our dataset, you can see the lower flows that start occuring around week 25 (early June) and last through the summer to week 45 (start of November). You can also bin values by day (‘annual-day’) or by month (‘annual-month’). The smaller the bins, the greater the variation.

[10]:
hf.cycleplot(Q.loc[:,'Upstream'], 'annual-week')
[10]:
(<Figure size 1008x432 with 1 Axes>,
 array([<matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D588E518>],
       dtype=object))
../_images/notebooks_Graphing_19_1.png

In this chart, we plot the hourly temperature for each month of the year. Note that the times are UTC, so midnight for this site should occur at hour 6.

[11]:
hf.cycleplot(T, 'diurnal', compare='month', y_label="Water Temperature (°C)")
[11]:
(<Figure size 1008x432 with 12 Axes>,
 array([<matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D58505C0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D4391860>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D580EB38>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5889E10>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D58D8128>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5A02400>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5A2D5F8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5A53898>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5A7CBA8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5AA5E80>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5C85198>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5CAC470>],
       dtype=object))
../_images/notebooks_Graphing_21_1.png

Plotting a histogram

Dataframes have a built-in histogram function.

We’ll plot each histogram with 20 bins (default is 10;) and we will have both sites share the same scale for the x axis (discharge) and y axis (count)

[12]:
Q.hist(bins=20, sharex=True, sharey=True)
[12]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D679AEB8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000001A8D5E132E8>]],
      dtype=object)
../_images/notebooks_Graphing_23_1.png

Box plots

Box plots are a great way to illustrate a distribution. In this chart, we’ll use boxplots to compare the two sites along the Shenandoah River:

[13]:
Q.plot.box(logy=True)
[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x1a8d60c3ac8>
../_images/notebooks_Graphing_25_1.png