R/plots.R

# lineplot() --------------------------------------------------------------
#' Aggregate Line Plot
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @export
lineplot <- function(list.q, query, reg = "Global") {
  # construct ttle
  ttle <- paste0(query, " (", reg, ")")

  # message
  print(paste0("Plotting ", ttle))

  # grab query data from restructured project data, subset by region
  df <- filter(list.q[[query]], region == reg)

  # get aggregate value, conditional on presence of "ghg" column
  if("ghg" %in% names(df)) {
    df <- group_by(df, Units, scenario, forcing, branch, year, ghg)
  } else {
    df <- group_by(df, Units, scenario, forcing, branch, year)
  }
  df <- df %>%
    summarise(value = sum(value)) %>%
    ungroup()

  # basic aggregate line plot
  p <- ggplot(df, aes(x = year, y = value)) +
    ggtitle(ttle) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    facet_grid(forcing ~ scenario) +
    ylab(unique(df$Units))

  # linetype conditional on presence of "GHG"
  if ("ghg" %in% names(df)) {
    p <- p + geom_line(aes(col = branch, linetype = ghg))
  } else {
    p <- p + geom_line(aes(col = branch))
  }

  # display plot
  return(list(p, ttle))
}


# barchart() --------------------------------------------------------------
#' Stacked Barchart
#'
#' This is the generic that dispatches different methods (below) according to class of list.q
#'
#' This plotting function outputs a *stacked* barchart. Queries which can be plotted using this function
#' need to have at least one more column than the base set of columns. The base set of columns is
#' units, scenario, forcing, branch, year, region, value. Technology and sector are common columns
#' which contain the keys which make a *stacked* barchart possible. constructPlot() is used in each method,
#' and requires a column that indicates the levels that each get their own color in the "stack", as
#' indicated in the plot's legend.
#'
#' Because barcharts can only be plotted for one forcing target, all methods require some dataPrep(),
#' which is found in utils.R. This function simply grabs the query data and filters it according to
#' user-input region and forcing target. Without any input, region defaults to "Global". dataPrep()
#' outputs this filtered query data as well as a string that combines query, region, and forcing. This
#' string is later used as the plot title.
#'
#' The final image is a grid of barcharts, where columns distinguish scenario-runs and rows distinguish
#' which branch of model development the scenarios were run on.
#'
#' barchart methods output a list whose first entry is the ggplot object, and the second entry
#' is the plot title. This is meant to facilitate programatically saving image files to a directory.
#'
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @export
barchart <- function(list.q, query, frc, reg = "Global") {

  # check presence of query in list.q
  if (! query %in% names(list.q)) error("Query not found in list.queries")

  params <- dataPrep(list.q, query, reg, frc)
  df <- params[[1]] # query data filtered by region and forcing target
  ttle <- params[[2]] # plot title "Query Name (Region) (Forcing)"


  # produce 3rd row of barcharts: Model.Minus.Int
  if (query == "Primary energy with CCS (Direct Equivalent)" |
      query == "Electricity generation by technology (inc solar roofs)" |
      query == "Ag Production by Crop Type" |
      query == "Average Yield" |
      query == "Land Allocation") {

    df <- Master.Minus.Development(df, query)
}

  #specific barchart method
  UseMethod("barchart", list.q)

}


# barchart.electricity() --------------------------------------------------
#' Barchart method for class=electricity
#'
#' Not all electricity queries in classes.csv can be plotted as a stacked barchart. The queries
#' supported by this method are:
#' Primary energy with CCS (Direct Equivalent)
#' Electricity generation by technology (inc solar roofs)
#'
#' Both barcharts display three rows: Master Branch, Development Branch, and Master.Minus.Development.
#' The third row is calculated using Master.Minus.Development(), found in utils.R.
#'
#' Both barcharts display three rows: Master Branch, Development Branch, and Master.Minus.Development.
#' The third row is calculated using master.minus.int(), found in utils.R.
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @param frc string, one of forcing targets in list.q[[query]]
#' @export
barchart.electricity <- function(list.q, query, frc, reg = "Global") {

  if (query == "Primary energy with CCS (Direct Equivalent)") {

    # Primary energy colors including CCS
    PAL_pri_ene <- c(
      "a oil" = "#d01c2a",
      "a oil CCS" = "#f7988f",
      "b natural gas" = "#25a9e0",
      "b natural gas CCS" = "#84e7f9",
      "c coal" = "#a0237c",
      "c coal CCS" = "#dab4c7",
      "d biomass" = "#00931d",
      "d biomass CCS" = "#88c892",
      "e nuclear" = "#ef8e27",
      "f hydro" = "#fdfa28",
      "g wind" = "#3d86f9",
      "h solar" = "#fdd67b",
      "i geothermal" = "#ad440c",
      "j traditional biomass" = "#11d081",
      "energy reduction" = "grey")

    p <- constructPlot(df, ttle, fuel, color_scheme=PAL_pri_ene)
    return(list(p, ttle))

  } else if (query == "Electricity generation by technology (inc solar roofs)") {

    # Color scheme for electricity generation by aggregate fuel
    elec_tech_colors <- c( "a Coal" = "#a0237c",
                           "b Coal w/CCS" = "#dab4c7",
                           "c Gas" = "#25a9e0",
                           "d Gas w/CCS" = "#84e7f9",
                           "e Oil" = "#d01c2a",
                           "f Oil w/CCS" = "#f7988f",
                           "g Biomass" = "#00931d",
                           "h Biomass w/CCS" = "#88c892",
                           "i Nuclear" = "#ef8e27",
                           "j Geothermal" = "#ad440c",
                           "k Hydro" = "#fdfa28",
                           "l Wind" = "#3d86f9",
                           "m Solar" = "#fdd67b",
                           "n CHP" = "#507fab",
                           "o Battery" = "#92a75d",
                           "energy reduction" = "grey")
    p <- constructPlot(df, ttle, agg.tech, color_scheme=elec_tech_colors)
    return(list(p, ttle))

  } else if (query == "Transportation final energy by fuel"  |
              query == "Building final energy by fuel"   |
              query == "Industry final energy by fuel") {

    enduse_fuel_numbered <- c( "1 liquids" = "#d01c2a",
                               "2 gas" = "#25a9e0",
                               "3 coal" = "#a0237c",
                               "4 biomass" = "#00931d",
                               "5 electricity" = "#ef8e27",
                               "6 hydrogen" = "#fffbac",
                               "7 trad biomass" = "#11d081",
                               "8 district heat" = "#b14d38",
                               "feedstocks" = "#ff7467",
                               "energy reduction" = "grey")
    p <- constructPlot(df, ttle, input, color_scheme=enduse_fuel_numbered)
    return(list(p, ttle))

  } else if (query == "Cogeneration by region") {

    p <- constructPlot(df, ttle, output)
    return(list(p, ttle))

  } else if (query == "Building floorspace") {
    p <- constructPlot(df, ttle, building)
    return(list(p, ttle))

  } else {
    warning(paste0("No barchart method found for query :", ttle))
  }

}


# barchart.water() --------------------------------------------------------
#' Barchart method for class=water
#'
#' This method currently supports all queries specified in the water class.
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @param frc string, one of forcing targets in list.q[[query]]
#' @export
barchart.water <- function(list.q, query, frc, reg = "Global") {

  p <- constructPlot(df, ttle, sector)
  return(list(p, ttle))

}

# barchart.land() ---------------------------------------------------------
#' Barchart method for class=land
#'
#' This method currently supports all queries specified in the land class.
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @param frc string, one of forcing targets in list.q[[query]]
#' @export
barchart.land <- function(list.q, query, frc, reg = "Global") {

  if (query == "Ag Production by Crop Type" |
      query == "Average Yield" |
      query == "Land Allocation") {

    # Color scheme for land type
    PAL_landuse<- c(
      "biomass" = "#00f629",
      "crops" = "#ffd125",
      "desert" = "#a7a7a7",
      "forest" = "#41a67a",
      "grass" = "#ffd081",
      "pasture" = "#aacf22",
      "shrub" = "#b14d00",
      "tundra" = "#938e15",
      "urban" = "#000000")

    # don't need to run an aggregation b/c ggplot sums all values in the same land_type
    p <- constructPlot(df, ttle, land_type, color_scheme=PAL_landuse)
    return(list(p, ttle))

  } else if (query == "Water Management Shares") {

    p <- constructPlot(df, ttle, water)
    return(list(p, ttle))

  } else if (query == "Fertilizer Tech Shares") {

    p <- constructPlot(df, ttle, fertilizer)
    return(list(p, ttle))

  } else {
    warning(paste0("No barchart method found for query :", ttle))
  }
}


# barchart.refining() -----------------------------------------------------
#' Barchart method for class=refining
#'
#' This method currently supports all queries specified in the land class except
#' the calculated query "Refined liquids use by technology and aggregate end-use".
#' This query could be stacked by either the technology or sector column.
#'
#' @param list.q list of queries, each query a single data.frame
#' @param query string, query must be in list.q
#' @param reg string, one of 32 GCAM regions or Global. Defaults to Global
#' @param frc string, one of forcing targets in list.q[[query]]
#' @export
barchart.refining <- function(list.q, query, frc, reg = "Global") {
  if (query == "Regional oil production by fuel" |
      query == "Oil Type Shares" ) {

    p <- constructPlot(df, ttle, technology)
    return(list(p,ttle))

  } else if (query == "Refined liquids production by technology") {

    p <- constructPlot(df, ttle, subsector)
    return(list(p, ttle))

  } else if (query == "Refined liquids use by aggregate end-use") {

    p <- constructPlot(df, ttle, sector)
    return(list(p, ttle))

  } else {
    warning(paste0("no barchart method found for query :", query))
  }
}


# constructPlot() ---------------------------------------------------------
#' Stacked barchart plotting function
#'
#' Each barchart method calls this function to construct its plot.
#'
#' This function is just a wrapper around code using the ggplot2 package. The input
#' specifies aesthetic mappings such as title, fill, and an optional color scheme.
#'
#' @param df data.frame, query data
#' @param ttle string, "Query Name (region) (forcing)"
#' @param keysCol unquoted column name, holds keys to use for ggplot fill parameter
#' @param color_scheme named vector, GCAM color scheme
#' @importFrom rlang quo_text
#' @import ggplot2
constructPlot <- function(df, ttle, keysCol, color_scheme = NULL) {

  # convert input column to quosure
  keysCol <- enquo(keysCol)

  print(paste0("Plot: ", ttle))
  p <- ggplot(df, aes(x = year, y = value)) +
    ggtitle(ttle) +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    facet_grid(branch ~ scenario, scales="free") + # to better show Master.Minus.Int row
    ylab(unique(df$Units)) +
    geom_bar(aes_string(fill = rlang::quo_text(keysCol)), stat = "identity") # convert quosure to string. TODO: use aes_(fill=keysCol) instead?

 if (!is.null(color_scheme)) {
   p <- p +
     scale_fill_manual(values=color_scheme)
 }

 p

}
# End ---------------------------------------------------------------------
xavier-gutierrez/validation_figures documentation built on May 24, 2019, 9:58 p.m.