In this lesson we will bring together all of the tools we have learned in previous lessons to create a “Fire Dashboard” function. This function will accept a date and then generate a plot of all fire locations and some summary barplots and donut plots.
The only thing new here is the creation of functions. Functions in R are objects in their own right and can be passed around just like any other variable. For our purposes, the simple syntax of functions is:
myfunction <- function(arg1, arg2, ... ) {
~statements~
return(object)
}
Arguments to functions may be named or not and the return() function is optional if your function is generating plots rather than returning a result.
Note: R uses pass-by-value rather than pass-by-reference. This means that a function cannot change the value of anything outside of its curly braces – its ‘scope’. However, a function does have read access to global variables
The rest of this lesson is a script that produces a “Fire Dashboard”. Your task is the following:
Good luck!
################################################################################
# Fire Dashboard
#
# Functions and main program to create a dahsboard plot based on fire_locations.csv data.
#
# Load packages
library(dplyr) # for "grammar of data manipulation"
library(maps) # for simple maps
library(RColorBrewer) # for color palettes
#
# Donut plot of total area per state
# df -- fires dataframe
# n -- number of states to include in donut plot
#
firePie <- function(df, n=10) {
# Utilize the dplyr package to quickly and cleanly select the necessary data.
df %>%
filter(type == "WF") %>%
select(state, area) %>%
group_by(state) %>%
summarize(total = sum(area, na.rm=TRUE)) %>%
arrange(desc(total)) ->
WFAreaByState
# Sanity check -- n must be <= number of states
if (n >= nrow(WFAreaByState)) (n = nrow(WFAreaByState))
# Plot only elements 1:n
pie(WFAreaByState$total[1:n], labels=WFAreaByState$state[1:n],
clockwise=TRUE,
col=brewer.pal(n,'Set2'), border='white', lwd=1.5, radius=1)
title("Total Wildfire Area", xpd=NA)
# Overlay a white circle to make a donut
par(new=TRUE)
pie(1, labels='', col='white', border='white', radius=.4)
# Return graphical parameter 'new' to default setting
par(new=FALSE)
}
#
# Bar plot of # of prescribed fires per state
# df -- fires dataframe
# n -- number of states to include in bar plot
#
fireBar <- function (df, n=10) {
oldPar <- par()
df %>%
filter(type == "RX") %>%
filter(state != "Unknown") %>%
select(state) %>%
group_by(state) %>%
summarize(count = length(state)) %>%
arrange(desc(count)) ->
RXCountByState
barplot(RXCountByState$count[1:n],
names.arg=RXCountByState$state[1:n],
horiz=TRUE, las=1,
col='yellow2')
title("Number of Prescribed Fires", xpd=NA)
}
#
# Map of all wildfire locations
# df -- fires dataframe
#
fireMap <- function (df) {
# ----- Style Section -----
# Allows for easily adjusting the map colors and points
cex <- 0.8
lwd <- 0.5
col_land <- adjustcolor('darkolivegreen3',1.0)
col_state <- 'gray50'
col_WF <- adjustcolor('black',.7)
col_RX <- adjustcolor('black',.7)
col_NON_US <- adjustcolor('black',.7)
colbg_WF <- adjustcolor('orangered',1.0)
colbg_RX <- adjustcolor('yellow',1.0)
colbg_NON_US <- adjustcolor('gray50',1.0)
pch_WF <- 24
pch_RX <- 21
pch_NON_US <- 23
xlim=c(-130,-53)
ylim=c(8,65)
mar = c(1,1,1,1)
# ----- Data Preparation -----
# Create WF and RX and NON_US subsets of the data
df %>%
filter(type == "WF") %>%
filter(state != "Unknown") %>%
select(longitude,latitude) ->
WF
df %>%
filter(type == "RX") %>%
filter(state != "Unknown") %>%
select(longitude,latitude) ->
RX
df %>%
filter(state == "Unknown") %>%
select(longitude,latitude) ->
NON_US
# Define countries of interest
countries <- c('usa','canada','mexico','cuba','belize','guatemala','bahamas',
'el salvador','honduras','nicaragua','costa rica','panama',
'dominican republic','puerto rico','haiti','jamaica')
# ----- Plot -----
# Create base map with national boundaries
map('world', region=countries,
xlim=xlim, ylim=ylim,
fill=TRUE, col=col_land,
mar=mar)
# Add state boundaries
map('state', add=TRUE, col=col_state)
# Add WF and RX and NON_US locations
points(WF$longitude, WF$latitude, col=col_WF, pch=pch_WF, cex=cex, bg=colbg_WF, lwd=lwd)
points(RX$longitude, RX$latitude, col=col_RX, pch=pch_RX, cex=cex, bg=colbg_RX, lwd=lwd)
points(NON_US$longitude, NON_US$latitude, col=col_NON_US, pch=pch_NON_US, cex=cex, bg=colbg_NON_US, lwd=lwd)
# Add a legend
legend(-130, 15.5, legend=c('Wildfires','Prescribed Fires', 'Non-US Fires'),
col=col_WF, pt.bg=c(colbg_WF,colbg_RX,colbg_NON_US), pch=c(pch_WF,pch_RX,pch_NON_US))
box('plot')
}
#
# Main function that puts everything together
# date -- Bluesky formatted date
#
fireDashboard <- function(date="2014080300") {
# URLs for all fire_locations datasets differ only in the 'date'
fires <- read.csv( paste0('http://smoke.airfire.org/bluesky-daily/output/hysplit-pp/NAM-4km/',date,'/data/fire_locations.csv') )
# Layout for two plots above and one below
layout( matrix(c(1,2,3,3), 2, 2, byrow = TRUE), widths=c(1,1), heights=c(3.7,5) )
# Pie chart of total wildfire area per state
firePie(fires)
# Barplot of # of prescribed fires per state
fireBar(fires)
# Map of fire locations
fireMap(fires)
# ----- Labeling -----
# Annotations here will appear on top of/relative to the last plot
# Convert incoming date to class POSIXct
datetime <- as.POSIXct( strptime(date, format="%Y%m%d%H", tz="GMT") )
# Create a nicely formatted string
dateString <- strftime(datetime, format="%m/%d/%Y %H:00 GMT", tz="GMT")
title(main="North American Wild and Prescribed Fires", line=2.5, xpd=NA)
title(dateString, line=1.0, xpd=NA)
# Return layout to default
layout(matrix(1))
}
We have defined the firePie(), fireBar() and fireMap() functions and a fireDashboard() function to put it all together. All we have to do is invoke this function with a date or let it use the builtin default:
# Create "Dashboard" plot
fireDashboard("2014081200")