knitr::opts_chunk$set(echo = TRUE) library(NWCEd) library(leaflet) library(ggplot2) library(dplyr) options(warn = -1)
Term | Defintion ---------------- | --------------------------------------------------- Time Series | A series of values obtained at successive times NWIS | National Water Information System Area Weighted Mean | The sum of area-weighted values divided by the total area Water Balance | A method used to account for water flowing in and out of a system Double-Mass Curve | A graphical method used to study consistency and trends in data
In order to put together an accurate water balance, we need to know the streamflow within the desired watershed to account for all the water entering and leaving the site. The United States Geological Survey (USGS) has put together a network called National Water Information System (NWIS). The NWIS collects, records, and stores streamflow data through the use of gages which are installed in several locations throughout the United States. For more information about the NWIS, please visit https://waterdata.usgs.gov/nwis/sw. To obtain a HUC ID that meets the desired requirements, first select the 12 Digit Huc layer in the Huc Layer:
dropdown box. Next, click on the Turn Gages On
to turn on the NWIS gages. Your screen should look similar to the image shown below in Figure 2 below.
The watershed we will analyze is the "Rock Canyon-Provo River" watershed located in Provo, Utah. In the search bar, search for "Provo River" and select "Provo River UT Utah County". Select Rock Canyon-Provo River watershed as shown in Figure 3 below. Note that there is a blue dot indicating the location of a NWIS gage within the boundary of the watershed.
After selecting the desired watershed, a new page will load which shows the HUC ID, the watershed name, and and some other information. Next, click on the Show Accumulated Water Budget
button located at the top left of the page. The precipitation, streamflow, and ET time series graph is displayed at the bottom of the page. A map of the watershed including the location of the NWIS gage is displayed towards the center of the page. These features are shown in Figure 4 below.
We now know for sure that this location has availabe precipitation, streamflow, and ET data. We know by looking at the upper left area of the page that the HUC ID is 160202030505. We can now download our desired datasets and begin our analysis. The ET and precipitation datasets have been plotted below.
Below is an enlarged map of the watershed we selected and the surrounding area. If you are viewing this lab in a web browser, you can place your cursor over the map and use the scroll wheel on the mouse to zoom in and out. Clicking and dragging the mouse on the map allows you to pan to different locations on the map.
library(NWCEd) library(leaflet) # Enter the huc12 to be analyzed like this: huc12<-"160202030505" NWCwatershed<-getNWCWatershed(huc="160202030505",local=FALSE) coords<-NWCwatershed$features[[1]]$geometry$coordinates[[1]][[1]] coords<-as.data.frame(matrix(unlist(coords),nrow=length(coords),byrow = T)) names(coords)<-c('lon','lat') leaflet() %>% setView(lng = mean(coords$lon), lat = mean(coords$lat), zoom = 9) %>% addTiles() %>% addGeoJSON(NWCwatershed, weight = 2, color = "#444444", fill = FALSE)
Zoom in closer to the watershed. What percentage of the watershed is within the city limits compared to in the mountainous areas? Do the people living within the watershed boundaries use all the water within the watershed? No, they don't. In fact, 70,000 acre-feet of water is diverted out of the Provo River to the Salt Lake Valley to the north via the 36 mile long Jordan Aqueduct (http://www.usbr.gov/projects/Project.jsp?proj_Name=Central+Utah+Project+-+Bonneville+Unit). Knowing how much water is contained within a given watershed is critical for supporting the population within and without the boundaries of the watershed.
Lets plot the annual precipitation, ET, and difference. The values of the precipitation and ET datasets from the NWC-DP are the area weighted mean precipitationa and ET values. The difference line is the difference between the annual precipitation and the annual ET. It tells us how much of the rainfall is left over after the effects of ET have taken place.
# Load required libraries. library(ggplot2) library(NWCEd) # Super basic plot of precip and et. NWCdata<-getNWCData(huc=huc12) # annualize et data. annual_dataet<-annualize(NWCdata$et, method=sum) # Add a group attribute to all et data. annual_dataet$group<-'ET' # Annualize prcp data. annual_dataprcp<-annualize(NWCdata$prcp, method=sum) # Add a group attribute to all prcp data. annual_dataprcp$group<-'P' # Merge prcp and et together. annual_union<-merge(annual_dataet,annual_dataprcp,by.x="year",by.y="year") # Create a difference variable. annual_diff<-as.data.frame(annual_union$data.y - annual_union$data.x) # Give the difference data a name. names(annual_diff) = c('data') # Add the difference data to a group. annual_diff$group<-'diff' # Add the same year data to the difference data. annual_diff$year<-annual_union$year
library(scales) library(ggplot2) require(stats) plotData<-rbind(annual_dataet,annual_dataprcp,annual_diff) ggplot(plotData, aes(x=year, y=data, group=group,colour = group)) + geom_line() + scale_x_discrete(name = "year") + ylab("mm") + theme(axis.text.x = element_text(angle = 45)) + labs(title = "Difference Between Precipitation and ET", colour = "Explanation") + theme(legend.position = c(0.91, 0.83)) + scale_color_manual(values=c("#990066", "#339966", "#FF0000"))
From the graph, we see the precipitation data in red, the ET data under the precipitation line in green, and the difference of the two datasets in maroon below the ET line. As the graph shows, there is only ET data available from the year 2000 through 2014 in our dataset. How does the precipitation line look in comparison to the ET line? Which shows more variation from year to year? Regarding precipitation, what years stick out to you? Does there appear to be any patterns? Could global climate variability be evidenced in the precipitation dataset?
It turns out there are more variables that go into balancing a water budget than just precipitation and ET. Water that percolates into the ground or is otherwise stored in lakes or reservoirs within the watershed must be accounted for as well. In the next step, we will discuss how to account for this unaccounted water using runoff data.
A common method of accounting for the water within the watershed, or in this case the HUC, is by performing a water balance. Water balances are used to account for all water flowing into and out of a system. Water balances are based on the principle that in a closed system mass is neither created or destroyed. Applying this to the water balance, all water flowing into the system must exit the system or be stored in the system. Lets look at the closed system defined by the 12-Digit HUC ID 031601090601 within the Town Creek-Cane Creek watershed. This HUC contains Jasper, Alabama within its boundaries. From the NWC-DP, the precipitation, ET, and streamflow datasets have been downloaded and plotted below for this HUC.
NWCdata<-getNWCData(huc="031501070601", local = FALSE) NWCwatershed<-getNWCWatershed(huc="031501070601",local=FALSE) areasqft<-NWCwatershed$features[[1]]$properties$areaacres*43560 NWCdata$et$data<-NWCdata$et$data*0.0032808 annual_dataet<-annualize(NWCdata$et, method=sum) annual_dataet$group<-'ET' NWCdata$prcp$data<-NWCdata$prcp$data*0.0032808 annual_dataprcp<-annualize(NWCdata$prcp, method=sum) annual_dataprcp$group<-'P' NWCdata$streamflow$data<-NWCdata$streamflow$data*60*60*24/areasqft annual_datastrf<-annualize(NWCdata$streamflow,method=sum) annual_datastrf$group<-'Q' annual_union<-merge(annual_dataet,annual_dataprcp,by.x="year",by.y="year") annual_union<-merge(annual_union,annual_datastrf,by.x="year",by.y="year") names(annual_union)<-c("year","ET","groupET","P","groupP","Q","groupQ") annual_diff<-as.data.frame(annual_union$P - annual_union$ET - annual_union$Q) names(annual_diff) = c('data') annual_diff$group<-'diff' annual_diff$year<-annual_union$year plotData<-rbind(annual_dataet,annual_dataprcp,annual_datastrf,annual_diff) ggplot(plotData, aes(x=year, y=data, group=group,colour = group)) + geom_line() + scale_x_discrete(name = "year") + ylab("ft") + theme(axis.text.x = element_text(angle = 45)) + labs(title = "Basic Diff Plot", colour = "Explanation") + scale_color_manual(values=c("#990066", "#339966", "#FF0000", "#3300FF"))
Precipitation, ET, streamflow, and the difference are marked in red, green, blue, and maroon, respectively. The diff line represents the leftover preciptiation after ET and streamflow have been subtracted from the original precipitation. The diff line includes water stored in the ground through percolation and in lakes and reservoirs within the system boundaries. Look at the diff line on the plot above. What years experienced positive storage? What years experienced negative storage? This may be a little bit difficult to read. Lets take a look at a different plot which shows the storage for the same location.
library(dplyr) NWCdata<-getNWCData(huc="031501070601", local = FALSE) NWCwatershed<-getNWCWatershed(huc="031501070601",local=FALSE) areasqft<-NWCwatershed$features[[1]]$properties$areaacres*43560 NWCdata$et$data<-NWCdata$et$data*0.0032808 annual_dataet<-annualize(NWCdata$et, method=sum) annual_dataet$group<-'ET' NWCdata$prcp$data<-NWCdata$prcp$data*0.0032808 annual_dataprcp<-annualize(NWCdata$prcp, method=sum) annual_dataprcp$group<-'P' NWCdata$streamflow$data<-NWCdata$streamflow$data*60*60*24/areasqft annual_datastrf<-annualize(NWCdata$streamflow,method=sum) annual_datastrf$group<-'Q' annual_union<-merge(annual_dataet,annual_dataprcp,by.x="year",by.y="year") annual_union<-merge(annual_union,annual_datastrf,by.x="year",by.y="year") names(annual_union)<-c("year","ET","groupET","P","groupP","Q","groupQ") annual_diff<-as.data.frame(annual_union$P - annual_union$ET - annual_union$Q) names(annual_diff) = c('data') annual_diff$group<-'diff' annual_diff$year<-annual_union$year annual_diff = annual_diff%>% mutate(pos = data >= 0) ggplot(annual_diff, aes(x=year, y=data, fill=pos)) + geom_bar(stat='identity', position = 'identity', color='black', size=0.25)+ scale_fill_manual(values=c('#FFDDDD','#CCEEFF'), guide = FALSE) + xlab("Year") + ylab("Annual Storage (ft)") + ggtitle("Annual Storage from 2000 to 2010")
This bar graph makes it very easy to see which years had positive storage and which years had negative storage. If we are assuming that the law of conservation of mass applies to water balances, how can we have negative storage? We must remember that negative storage for our time series simply means that there is no water being stored. In our case, there is water being pulled out of storage. Where are possible locations for water to be stored within this HUC? Using the same methods as described in Step 2 zoom in and look for possible storage places within the system.
# Enter the huc12 to be analyzed like this: huc12<-"031601090601"
library(NWCEd) library(leaflet) # Get watershed geometry and put it on a map. NWCwatershed<-getNWCWatershed(huc=huc12,local=FALSE) coords<-NWCwatershed$features[[1]]$geometry$coordinates[[1]][[1]] coords<-as.data.frame(matrix(unlist(coords),nrow=length(coords),byrow = T)) names(coords)<-c('lon','lat') leaflet() %>% setView(lng = mean(coords$lon), lat = mean(coords$lat), zoom = 9) %>% addTiles("http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}") %>% addWMSTiles(baseUrl = "https://cida.usgs.gov/nwc/geoserver/gwc/service/wms", options = WMSTileOptions(format = "image/png", transparent = TRUE, opacity = 1), attribution = "Tiles © Esri — Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012") %>% addGeoJSON(NWCwatershed, weight = 5, color = "#ff7800", fill = FALSE)
Storage is mainly comprised of ground water, although additional storage areas can include lakes and rivers.
How do we know if our precipitation data is good to use? In the field, there is the possibility that rain gages are moved or are damaged for a period of time. Problems that occur in the field must be taken into consideration and the data adjusted to reflect the conditions of the site being analyzed. One method used to identify inconsistencies in a precipitation dataset is a Double-Mass Curve. For analyzing precipitation data at a site, the annual precipitation data of nearby rain gages are collected and cumulated. The mean cumulative annual data is then plotted against the mean annual cumulative precipitation for the surrounding sites including the site being analyzed. For more information on double-mass curves, please visit https://pubs.usgs.gov/wsp/1541b/report.pdf.
Lets check the consistency and long-term trends of the precipitation data for HUC# 031601090601. For this exercise it is important to note that the precipitation data used is actually the area weighted mean precipitation based on data obtained through rain gages. The surrounding sites are the nearest surrounding 12-Digit HUCs. For the purposes of the exercise, these differences are negligible. Below is the code used to collect, cumulate, find the cumulative mean for 4 sites, and plot the results.
# Download data from NWC-DP for HUC# 031601090601 NWCdata<-getNWCData(huc="031601090601", local = FALSE) # Assign NWCdataprcp variable the precipitation dataset NWCdataprcp1<-NWCdata$prcp # Convert units from mm to inches NWCdataprcp1$data<-NWCdataprcp1$data*.0393701 # Convert data from daily to annual precipitation NWCdataprcpsumannual1<-annualize(NWCdataprcp1, method = sum) # Cumulates annual precipitation data for the site NWcdataprcpsumannualcum1<-cumsum(NWCdataprcpsumannual1$data) # Repeat previous steps for next three HUC# NWCdata<-getNWCData(huc="031601090405", local = FALSE) NWCdataprcp2<-NWCdata$prcp NWCdataprcp2$data<-NWCdataprcp2$data*.0393701 NWCdataprcpsumannual2<-annualize(NWCdataprcp2, method = sum) NWcdataprcpsumannualcum2<-cumsum(NWCdataprcpsumannual2$data) NWCdata<-getNWCData(huc="031601090403", local = FALSE) NWCdataprcp3<-NWCdata$prcp NWCdataprcp3$data<-NWCdataprcp3$data*.0393701 NWCdataprcpsumannual3<-annualize(NWCdataprcp3, method = sum) NWcdataprcpsumannualcum3<-cumsum(NWCdataprcpsumannual3$data) NWCdata<-getNWCData(huc="031601090308", local = FALSE) NWCdataprcp4<-NWCdata$prcp NWCdataprcp4$data<-NWCdataprcp4$data*.0393701 NWCdataprcpsumannual4<-annualize(NWCdataprcp4, method = sum) NWcdataprcpsumannualcum4<-cumsum(NWCdataprcpsumannual4$data) # Averaging the annual precipitation for the 4 sites annualaverage <- (NWCdataprcpsumannual1$data + NWCdataprcpsumannual2$data + NWCdataprcpsumannual3$data + NWCdataprcpsumannual4$data)/4 # Cumulates the averaged annual precipitation for the 4 sites annualaveragecum<-cumsum(annualaverage) # Creates a dataframe with mean cumulative annual precipitation and the cumulative annual precipitation for the first HUC plot1<-data.frame(x = annualaveragecum, y = NWcdataprcpsumannualcum1) # Plots the newly created dataframe ggplot(plot1, aes(x=x, y=y)) + geom_point() + geom_smooth(color="blue") + xlab("Mean Cumulative Precipitation (inches) ") + ylab("Cumulative Precipitation for HUC# 031601090601 (inches)") + ggtitle("Double Mass Analysis for HUC# 031601090601 Precip Data") + theme(panel.background = element_rect(fill = "grey75"))
As we can see, the data points for the most part fall into a straight line. This indicates there is strong correlation among the data points and the measurements are consistent throughout the dataset. Lets take a look at a case where eroneous data are plotted on a double-mass curve.
# Download data from NWC-DP for HUC# 150601060306 NWCdata<-getNWCData(huc="150601060306", local = FALSE) # Assign NWCdataprcp variable the precipitation dataset NWCdataprcp1<-NWCdata$prcp # Convert units from mm to inches NWCdataprcp1$data<-NWCdataprcp1$data*.0393701 # Convert data from daily to annual precipitation NWCdataprcpsumannual1<-annualize(NWCdataprcp1, method = sum) # Cumulates annual precipitation data for the site NWcdataprcpsumannualcum1<-cumsum(NWCdataprcpsumannual1$data) # Repeat previous steps for next three HUC# NWCdata<-getNWCData(huc="150701020908", local = FALSE) NWCdataprcp2<-NWCdata$prcp NWCdataprcp2$data<-NWCdataprcp2$data*.0393701 NWCdataprcpsumannual2<-annualize(NWCdataprcp2, method = sum) NWcdataprcpsumannualcum2<-cumsum(NWCdataprcpsumannual2$data) NWCdata<-getNWCData(huc="150601060305", local = FALSE) NWCdataprcp3<-NWCdata$prcp NWCdataprcp3$data<-NWCdataprcp3$data*.0393701 NWCdataprcpsumannual3<-annualize(NWCdataprcp3, method = sum) NWcdataprcpsumannualcum3<-cumsum(NWCdataprcpsumannual3$data) # Read in manually altered dataset csv_data<-download.file("https://rawgit.com/jnelson7/NWCEd/43da87970865520fa698640f726e8762b348e95c/inst/extdata/doublemassplot2sheet1.csv", quiet = TRUE, destfile = './doublemassplot2sheet1.csv') NWCdataprcpsumannual4<-read.csv('./doublemassplot2sheet1.csv') csv_data2<-download.file("https://rawgit.com/jnelson7/NWCEd/43da87970865520fa698640f726e8762b348e95c/inst/extdata/doublemassplot2sheet2.csv", quiet = TRUE, destfile = './doublemassplot2sheet2.csv') NWcdataprcpsumannualcum4<-cumsum(NWCdataprcpsumannual4$data) # Averaging the annual precipitation for the 4 sites annualaverage <- (NWCdataprcpsumannual1$data + NWCdataprcpsumannual2$data + NWCdataprcpsumannual3$data + NWCdataprcpsumannual4$data)/4 # Cumulates the averaged annual precipitation for the 4 sites annualaveragecum<-cumsum(annualaverage) # Creates a dataframe with mean cumulative annual precipitation and the cumulative annual precipitation for the first HUC plot4<-data.frame(x = annualaveragecum, y = NWcdataprcpsumannualcum4) # Separates dataset at the curve break plotsegment<-plot4[c(1:17),] plotsegment2<-plot4[c(17:35),] # Plots the newly created dataframe ggplot(plot4, aes(x=x, y=y)) + geom_point() + geom_smooth(color="blue") + xlab("Mean Cumulative Precipitation (inches) ") + ylab("Cumulative Precipitation for HUC# 031601090601 (inches)") + ggtitle("Hypothetical HUC near Phoenix, AZ") + theme(panel.background = element_rect(fill = "grey75")) + annotate("text", x=365, y=175, label = "Break in Curve", size = 4) ggplot(plot4, aes(x=x, y=y)) + geom_smooth(data = plotsegment, color = "blue") + geom_smooth(data = plotsegment2, color = "yellow") + annotate("text", x=365, y=175, label = "Break in Curve", size = 4) + theme(panel.background = element_rect(fill = "grey75")) + xlab("Mean Cumulative Precipitation (inches) ") + ylab("Cumulative Precipitation for HUC# 031601090601 (inches)") + ggtitle("Hypothetical HUC near Phoenix, AZ")
We would expect the data points to plot in a linear fashion. However, when we look at this double-mass curve, we can clearly see a break in the curve. If we were to do some research on this hypothetical rain gage, we would find that development occured in close proximity to the gage. A sprinkler system was installed and the gage was collecting additional readings when the sprinklers were running. We are needing to adjust our data to reflect the natural conditions without the sprinklers. To do this, we can multiply the "bad" data by the ratio of the slope of the "good" data. We can use the following equation to help us adjust our data:
$$P_a=\frac{b_a}{b_0}*P_0$$
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.