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")

plot of chunk unnamed-chunk-2