SAVE NOAA!


NOAA meatball


The products on this page rely on data from the National Oceanic and Atmospheric Administration (NOAA). NOAA is a critical tax-funded federal agency whose data collection, modeling and science capabilities, and personnel expertise keep the country safer and more prosperous—all at a cost of 6¢ per day per taxpayer. If you are visiting this page and reading this, you have an interest in NOAA’s science, service, and stewardship to the nation. Contact your representatives in Congress today to demand that NOAA employees are restored, facilities and resources are maintained, and budget is preserved.

How are these records calculated?

All data from the beginning of each time series to the present are retrieved from the NOAA CO-OPS Tides and Currents data portal and saved to file to avoid having to repeatedly re-download the historical data. Subsequent data updates retrieve from the most recently saved timestamp onward and append these new data to the saved historical record.

Six-minute data are used whenever possible and hourly data otherwise. Any observations flagged by NOAA as being suspect for any reason (flag > 0) are discarded. Examples of flagged data are a minimum or maximum value or a rate of change exceeding an acceptable tolerance. Air and water temperatures equal to 31.8°F are also removed, as this is a fill value signifying bad data.

A day is allowed to have up to four hours of missing data to be counted in the daily climatology, and a month is allowed up to two days of missing data to be counted in the monthly climatology. Data gaps are acceptable (averages omit NAs) as long as they do not collectively exceed these thresholds.

All of the statistics and records herein start with one of three quantities: daily highs, daily lows, or daily averages. Each of these is first calculated for each environmental variable (i.e., air temperature, water temperature, water level) and for every day in the data time series as follows.

Daily High

This is the maximum temperature recorded on any given day. Let \(X\) be a 24-hr time series of some environmental variable sampled \(n\) times during the day:

\[X = \{x_1, x_2,...,x_n\}\]

The daily high is the maximum value in this observation set:

\[\text{daily high} = \max(X) \tag{1}\]

Daily Low

Similarly, the daily low is the minimum temperature recorded on any given day:

\[\text{daily low} = \min(X) \tag{2}\]

Daily Average

The daily average is the average of all recorded observations of a given variable on any given day. It can be calculated in one of two ways:

Method 1: True average

This is the conventional method of calculating an average: the sum of all observations during the 24-hour period divided by the number of observations, \(n\):

\[\text{true daily average} = \frac{1}{n} \sum_{i=1}^n x_i \tag{3}\]

Method 2: Meteorological average

The meteorological average is customarily calculated using only the maximum and minimum values recorded during a 24-hour period:

\[\text{meteorological daily average} = \frac{\max(X) + \min(X)}{2} \tag{4}\]

This project uses the true average (Equation 3) for all calculations.

Daily statistics are calculated next, followed by monthly statistics.

Cosine regression curves are fit to daily averages, average highs, and average lows for plotting purposes.

Daily Climatology and Records

Daily climatology and records are calculated for each day-of-year (DOY), where

Jan 1 \(\longrightarrow\) Day 1
Jan 2 \(\longrightarrow\) Day 2

Feb 28 \(\longrightarrow\) Day 59
Feb 29 \(\longrightarrow\) Day 60

Dec 30 \(\longrightarrow\) Day 365
Dec 31 \(\longrightarrow\) Day 366

Instead of eliminating February 29 on leap years, Day 60 is skipped in years that are not leap years. Thus, December 31 is always Day 366. Days start at midnight (00:00) and go until 23:59 (11:59 PM) local time.

DOY Daily Average

The DOY daily average is the average of all daily averages for any given DOY. It is calculated by taking the daily averages from Equation 3, grouping them by DOY, and calculating the average for each DOY.

Let \(\textbf{A}\) be a matrix of daily averages from Equation 3 arranged with years in rows and DOY in columns, and for simplicity, let subscript \(y\) indicate year and \(d\) indicate DOY:

\[\textbf{A} = (a_{yd}) = \left( \begin{array}{cccc} a_{1,1} & a_{1,2} & ... & a_{1,366} \\ a_{2,1} & a_{2,2} & ... & a_{2,366} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ a_{y,1} & a_{y,2} & ... & a_{y,366} \end{array} \right) \tag{5}\]

The DOY daily average is the average over each column:

\[\text{DOY daily average} = \frac{1}{Y}\sum_{y=1}^Y a_{yd} \tag{6}\]

where \(Y\) is the number of years in the observational time series.

Note

The Daily Average reported in the statistics dashboard are DOY daily averages from Equation 6, not to be confused with Equation 3 or 4. For the sake of visualization, a cosine regression is fit to these data and shown on the plots.

Record High Daily Average

The record high daily average is the maximum daily average for any given DOY. It is determined by taking the daily averages from Equation 3, grouping them by DOY, and finding the maximum value for each DOY. Given \(\textbf{A}\) from Equation 5 above:

\[\text{record high daily average} = \max\{|a_{yd}|: d=1,2,...,366\} \tag{7}\]

Record Low Daily Average

The record low daily average is the minimum daily average for any given DOY. It is determined by taking the daily averages from Equation 3, grouping them by DOY, and finding the minimum value for each DOY. Given \(\textbf{A}\) from Equation 5 above:

\[\text{record low daily average} = \min\{|a_{yd}|: d=1,2,...,366\} \tag{8}\]

Average High

The average high is the average of all daily highs for any given DOY. It is determined by taking the daily highs from Equation 1, grouping them by DOY, and calculating the average for each DOY.

Let \(\textbf{H}\) be a matrix of daily highs from Equation 1 arranged with years in rows and DOY in columns, and for simplicity, let subscript \(y\) indicate year and \(d\) indicate DOY:

\[\textbf{H} = (h_{yd}) = \left( \begin{array}{cccc} h_{1,1} & h_{1,2} & ... & h_{1,366} \\ h_{2,1} & h_{2,2} & ... & h_{2,366} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ h_{y,1} & h_{y,2} & ... & h_{y,366} \end{array} \right) \tag{9}\]

The average high is the average over each column:

\[\text{average high} = \frac{1}{Y}\sum_{y=1}^Y h_{yd} \tag{10}\]

where \(Y\) is the number of years in the observational time series.

Plots illustrate a cosine regression fit to these data for the sake of visualization.

Record High

The record high is the maximum daily high for any given DOY. It is determined by taking the daily highs from Equation 1, grouping them by DOY, and finding the maximum value for each DOY. Given \(\textbf{H}\) from Equation 9 above:

\[\text{record high} = \max\{|h_{yd}|: d=1,2,...,366\} \tag{11}\]

Lowest High

The lowest high is the minimum daily high for any given DOY. It is determined by taking the daily highs from Equation 1, grouping them by DOY, and finding the minimum value for each DOY. Given \(\textbf{H}\) from Equation 9 above:

\[\text{lowest high} = \min\{|h_{yd}|: d=1,2,...,366\} \tag{12}\]

Average Low

The average low is the average of all daily lows for any given DOY. It is determined by taking the daily lows from Equation 2, grouping them by DOY, and calculating the average for each DOY.

Let \(\textbf{L}\) be a matrix of daily lows from Equation 2 arranged with years in rows and DOY in columns, and for simplicity, let subscript \(y\) indicate year and \(d\) indicate DOY:

\[\textbf{L} = (l_{yd}) = \left( \begin{array}{cccc} l_{1,1} & l_{1,2} & ... & l_{1,366} \\ l_{2,1} & l_{2,2} & ... & l_{2,366} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ l_{y,1} & l_{y,2} & ... & l_{y,366} \end{array} \right) \tag{13}\]

The average low is the average over each column:

\[\text{average low} = \frac{1}{Y}\sum_{y=1}^Y l_{yd} \tag{14}\]

where \(Y\) is the number of years in the observational time series.

Plots illustrate a cosine regression fit to these data for the sake of visualization.

Highest Low

The highest low is the maximum daily low for any given DOY. It is determined by taking the daily lows from Equation 2, grouping them by DOY, and finding the maximum value for each DOY. Given \(\textbf{L}\) from Equation 13 above:

\[\text{highest low} = \max\{|l_{yd}|: d=1,2,...,366\} \tag{15}\]

Record Low

The record low is the minimum daily low for any given DOY. It is determined by taking the daily lows from Equation 2, grouping them by DOY, and finding the minimum value for each DOY. Given \(\textbf{L}\) from Equation 13 above:

\[\text{record low} = \min\{|l_{yd}|: d=1,2,...,366\} \tag{16}\]

Number of Years in Record

The number of years of data available varies from day to day and between variables due to sensor availability, gaps in the observational record, or bad data being filtered out. Years are tallied by grouping the entire time series by DOY and counting the number of years for each day. For example, given \(\textbf{A}\) from Equation 5 above, the number of years available for each DOY is the total number of unique years in each column.

Monthly Climatology and Records

Monthly climatology and records are calculated in the same way as daily climatology and records except that daily highs, lows, and averages are grouped by calendar month instead of DOY.

Monthly Average

The monthly average is the average of all daily averages for any given month. It is calculated by taking the daily averages from Equation 3, grouping them by calendar month, and calculating the average for each month.

Let \(\textbf{A}\) now be a matrix of daily averages from Equation 3 arranged with years in rows and months in columns, and for simplicity, let subscript \(y\) indicate year and \(m\) indicate month:

\[\textbf{A} = (a_{ym}) = \left( \begin{array}{cccc} a_{1,1} & a_{1,2} & ... & a_{1,12} \\ a_{2,1} & a_{2,2} & ... & a_{2,12} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ a_{y,1} & a_{y,2} & ... & a_{y,12} \end{array} \right) \tag{17}\]

The monthly average is the average over each column:

\[\text{monthly average} = \frac{1}{Y}\sum_{y=1}^Y a_{ym} \tag{18}\]

where \(Y\) is the number of years in the observational time series.

Plots illustrate a cosine regression fit to these data for the sake of visualization.

Record High Monthly Average

The record high monthly average is the maximum daily average for any given calendar month. It is determined by taking the daily averages from Equation 3, grouping them by calendar month, and finding the maximum value for each month. Given \(\textbf{A}\) from Equation 17 above:

\[\text{record high monthly average} = \max\{|a_{ym}|: m=1,2,...,12\} \tag{19}\]

Record Low Monthly Average

The record low monthly average is the minimum daily average for any given calendar month. It is determined by taking the daily averages from Equation 3, grouping them by calendar month, and finding the minimum value for each month. Given \(\textbf{A}\) from Equation 17 above:

\[\text{record low monthly average} = \min\{|a_{ym}|: m=1,2,...,12\} \tag{20}\]

Average High

The average high is the average of all daily highs for any given calendar month. It is determined by taking the daily highs from Equation 1, grouping them by calendar month, and calculating the average for each month.

Let \(\textbf{H}\) now be a matrix of daily highs from Equation 1 arranged with years in rows and months in columns, and for simplicity, let subscript \(y\) indicate year and \(m\) indicate month:

\[\textbf{H} = (h_{ym}) = \left( \begin{array}{cccc} h_{1,1} & h_{1,2} & ... & h_{1,12} \\ h_{2,1} & h_{2,2} & ... & h_{2,12} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ h_{y,1} & h_{y,2} & ... & h_{y,12} \end{array} \right) \tag{21}\]

The average high is the average over each column:

\[\text{average high} = \frac{1}{Y}\sum_{y=1}^Y h_{ym} \tag{22}\]

where \(Y\) is the number of years in the observational time series.

Plots illustrate a cosine regression fit to these data for the sake of visualization.

Record High

The record high is the maximum daily high for any given calendar month. It is determined by taking the daily highs from Equation 1, grouping them by calendar month, and finding the maximum value for each month. Given \(\textbf{H}\) from Equation 21 above:

\[\text{record high} = {\max}_m |h_{ym}| = \max\{|h_{ym}|: m=1,2,...,12\} \tag{23}\]

Lowest High

The lowest high is the minimum daily high for any given calendar month. It is determined by taking the daily highs from Equation 1, grouping them by calendar month, and finding the minimum value for each month. Given \(\textbf{H}\) from Equation 21 above:

\[\text{lowest high} = {\min}_m |h_{ym}| = \min\{|h_{ym}|: m=1,2,...,12\} \tag{24}\]

Average Low

The average low is the average of all daily lows for any given calendar month. It is determined by taking the daily lows from Equation 2, grouping them by calendar month, and calculating the average for each month.

Let \(\textbf{L}\) now be a matrix of daily lows from Equation 2 arranged with years in rows and months in columns, and for simplicity, let subscript \(y\) indicate year and \(m\) indicate month:

\[\textbf{L} = (l_{ym}) = \left( \begin{array}{cccc} l_{1,1} & l_{1,2} & ... & l_{1,12} \\ l_{2,1} & l_{2,2} & ... & l_{2,12} \\ \vdotswithin{=} & \vdotswithin{=} & & \vdotswithin{=} \\ l_{y,1} & l_{y,2} & ... & l_{y,12} \end{array} \right) \tag{25}\]

The average low is the average over each column:

\[\text{average low} = \frac{1}{Y}\sum_{y=1}^Y l_{ym} \tag{26}\]

where \(Y\) is the number of years in the observational time series.

Plots illustrate a cosine regression fit to these data for the sake of visualization.

Highest Low

The highest low is the maximum daily low for any given calendar month. It is determined by taking the daily lows from Equation 2, grouping them by calendar month, and finding the maximum value for each month. Given \(\textbf{L}\) from Equation 25 above:

\[\text{highest low} = \max\{|l_{ym}|: m=1,2,...,12\} \tag{27}\]

Record Low

The record low is the minimum daily low for any given calendar month. It is determined by taking the daily lows from Equation 2, grouping them by calendar month, and finding the minimum value for each month. Given \(\textbf{L}\) from Equation 25 above:

\[\text{record low} = \min\{|l_{ym}|: m=1,2,...,12\} \tag{28}\]

Number of Years in Record

The number of years of data available varies from month to month and between variables due to sensor availability, gaps in the observational record, or bad data being filtered out. Years are tallied by grouping the entire time series by calendar month and counting the number of years for each month. For example, given \(\textbf{A}\) from Equation 17 above, the number of years available for each month is the total number of unique years in each column.

Record Counts

Daily Records Set By Year

The total number of the daily records set each year are tallied up by year. Daily records include all of the following:

  • Record high daily average
  • Record low daily average
  • Lowest high
  • Record high
  • Highest low
  • Record low

Monthly Records Set By Year

The total number of the monthly records set each year are tallied up by year. Monthly records include all of the following:

  • Record high monthly average
  • Record low monthly average
  • Lowest high
  • Record high
  • Highest low
  • Record low

Water Level Trend

This plot shows the full water level time series with any long term trend observed at the site. Water level data are the only data that are quality controlled and, in many locations, the time series span several decades, making it possible to discern trends. Let \(L\) be the full time series of water levels observed at a given site, sampled either hourly or every six minutes, containing a total of \(n\) observations:

\[L = \{l_1, l_2,...,l_n\}\]

Monthly average water levels are calculated from daily averaged calculated from Equation 4 over the entire time series and a simple linear interpretation model is applied to fill missing data. The time series is then normalized to the interval \([0,1]\):

\[D = \frac{L - \min(L)}{\max(L) - \min(L)} \tag{29}\]

where \(\min(L)\) and \(\max(L)\) are the minimum and maximum of the entire time series, respectively. The seasonal signal is then removed from the normalized time series using an additive model from the Python package statsmodels with a quarterly period (4 seasons per year.) The de-seasonalized time series is then un-normalized using the inverse of Equation 30:

\[D * \big(\max(L) - \min(L)\big) + \min(L) \tag{30}\]

Finally, a linear regression is applied to the de-seasonalized time series to discern any long term trend.

Note

This plot is only available for sites containing full time series of water level obervations. Some time series have been interrupted by storms or other logistical challenges, making it either impossible or uninstructive to make this plot.

Back to top