#'Build an exceedance probability colour map
#'
#'This function builds a map that visualises the probability of exceeding some
#'nominated threshold of concern.
#'
#'If \code{geoData} remains \code{NULL}, the function will produce a map of
#'plotted points representing specific sites; in this case, the data frame must
#'include latitude and longitude coordinates in columns \code{"long"} and
#'\code{"lat"}.
#'
#'@param data A data frame containing columns that house estimates of the mean,
#'standard deviation (or margin of error) and exceedance probability (optional).
#'A number of options are considered for calculating the probability of exceeding
#'a threshold. See below for more information.
#'@param pdflist A list capturing the pdf function that defines the distribution function to use to
#'calculate the probabilities of exceedance. By default this is NULL and assumes
#'the exceedance probabilities have been calculated outside of the function and passed
#'as a third column of the data frame. Functions need to conform to the class
#'of distribution functions available within R through the \code{stats} package.
#'@param geoData An sf or sp object.
#'@param id Name of the common column shared by the objects passed to
#' \code{data} and \code{geoData}. The exceedance probability in the data frame
#' will be matched to the geographical regions through this column.
#'@param key_label Label of legend.
#'@param border Name of geographical borders to be added to the map. It must be
#' one of \code{\link[maps]{county}}, \code{\link[maps]{france}},
#' \code{\link[maps]{italy}}, \code{\link[maps]{nz}},
#' \code{\link[maps]{state}}, \code{\link[maps]{usa}} or
#' \code{\link[maps]{world}} (see documentation for
#' \code{\link[ggplot2]{map_data}} for more information). The borders will be
#' refined to match latitute and longtidue coordinates from the geoData argument.
#'@param palette Name of colour palette. Colour palette names include
#' \code{"YlOrBr"}, \code{"YlOrRd"}, \code{"YlGnBu"} and \code{"PuBuGn"}.
#'@param size An integer between 1 and 20. Value controls the size of points
#' when \code{geoData = NULL}. If \code{size = NULL}, the points will remain
#' the default size.
#'
#' @details An exceedance probability map can be produced using:
#' (i) precalculated exceedance probabilities, which are provided as a third column
#' to the input dataframe; or
#' (ii) exceedance probabilities that are calculated within the function using one of
#' the standard probability distributions (e.g. \code{pnorm}) provided in the \code{stats}
#' package in R, or
#' (iii) exceedance probabilities that are calculated through a user defined function that
#' is passed to the package which conforms to a similar structure as the suite of
#' \code{Distributions} available in R. Examples are provided below.
#'
#'@examples
#'data(us_data)
#'data(us_geo)
#'poverty <- read.uv(data = us_data, estimate = "pov_rate", error = "pov_moe")
#'
#'# Exceedance probability map: Pr[X > 30] (Exponential Distribution)
#'#---- define probability distribution
#'pd <- quote({ pexp(q, rate, lower.tail = FALSE) })
#'#---- define argument listing
#'args <- quote({ list(rate = 1/estimate) })
#'#---- capture distribution and arguments in a single list
#'pdflist <- list(dist = pd, args = args, th = 30)
#'map <- build_emap(data = poverty, pdflist = pdflist, geoData = us_geo, id = "GEO_ID",
#' border = "state", key_label = "Pr[X > 30]")
#'view(map) + ggplot2::ggtitle("Proper use of build_emap (appropriate distribution choice)")
#'
#'# Example where an inappropriate distributions is tried
#'# Exceedance probability map: Pr[X>30] (Normal Distribution)
#'
#'#---- define probability distribution
#'pd <- quote({ pnorm(q, mean, sd, lower.tail = FALSE) })
#'#---- define argument listing
#'args <- quote({ list(mean = estimate, sd = error/1.645) })
#'#---- capture distribution and arguments in a single list
#'pdflist <- list(dist = pd, args = args, th = 30)
#'map <- build_emap(data = poverty, pdflist = pdflist, geoData = us_geo, id = "GEO_ID",
#' border = "state", key_label = "Pr[X > 30]")
#'view(map) + ggplot2::ggtitle("Misuse of build_emap (inappropriate distribution choice)")
#'
#'# Example where exceedance probabilities have been supplied (GBR Example)
#' # Load Upper Burdekin Data
#' data(UB)
#'
#'# Build Palette
#' exc_pal <- build_palette(name = "usr", colrange = list(colour = c("yellow", "red"),
#' difC = c(1, 1)))
#' view(exc_pal)
#'# Create map and view it
#' tss <- read.uv(data = UB_tss, estimate = "TSS", error = "TSS Error", exceedance = "TSS_exc1")
#' map <- build_emap(data = tss, geoData = UB_shp, id = "scID",
#' key_label = "Pr[TSS > 837mg/L]")
#' view(map)
#'
#'
#'@import "ggplot2"
#'@importFrom "dplyr" "left_join"
#'@importFrom "plyr" "join"
#'@importFrom "dplyr" "rename"
#'@importFrom "dplyr" "%>%"
#'@importFrom "ggmap" "make_bbox"
#'@importFrom "spbabel" "sptable"
#'@export
build_emap <-
function(data,
pdflist = NULL,
geoData = NULL,
id = NULL,
key_label,
palette = "YlOrRd",
size = NULL,
border = NULL) {
if (is.null(geoData)) {
l1 <- match("long", names(data))
l2 <- match("lat", names(data))
if (any(is.na(c(l1, l2))))
stop("There must be coordinates in data columns named long and lat.\n")
}
if (!is.null(geoData) & is.null(id)) {
stop("Missing id. Must be a common column shared by data and geoData.")
}
if (!is.null(border)) {
m <-
(border %in% c("county", "france", "italy", "nz", "state", "usa", "world"))
if (length(m) == 0) {
stop(
"Border name not recognised. Must be one of county, france, italy, nz, state, usa or world \n
(see documentation for map_data function in ggplot2 for more information)"
)
} else {
bord <- map_data(border)
}
} else {
long <- numeric(0)
lat = numeric(0)
bord <- data.frame(long = long,
lat = lat,
group = numeric(0))
}
if (!is.null(size)) {
s <- seq(1, 20, by = 1)
if (!(size %in% s) & !is.null(size)) {
stop("Size not recognised. Must be an integer between 1 and 20.")
}
}
#check palette name
if (!(palette %in% c("YlOrBr", "YlOrRd", "YlGnBu", "PuBuGn"))) {
stop(
"Palette name not recognised. Must be one of YlOrBr, YlOrRd, YlGnBu or PuBuGn, \n
(see documentation for scale_fill_distiller in ggplot2 for more information).\n"
)
}
# determine whether geoData has been entered by user
# if so, link geoData and data and plot
if (!is.null(geoData) &
inherits(geoData, "SpatialPolygonsDataFrame")) {
geoData@data <-
geoData@data %>% dplyr::mutate_if(is.factor, as.character)
geoData@data <- left_join(geoData@data, data, by = id)
geoData@data$id <- rownames(geoData@data)
region_coord <- sptable(geoData, region = "id")
region_coord <-
plyr::rename(region_coord,
c(
object_ = "id",
x_ = "long",
y_ = "lat",
branch_ = "group"
))
output_data <- plyr::join(region_coord, geoData@data, by = "id")
bbox <- make_bbox(lat = lat,
lon = long,
data = output_data)
} else if (!is.null(geoData) & inherits(geoData, "sf")) {
output_data <- left_join(geoData, data, by = id)
bbox <- NULL
} else {
output_data <- data
bbox <- make_bbox(lat = lat,
lon = long,
data = output_data)
}
if (is.null(pdflist)) {
# assume 3 columns (pr_exc, estimate, error)
col_ids <- match(names(data)[1:3], names(output_data))
names(output_data)[col_ids] <- c("pr_exc", "estimate", "error")
} else {
# assume 2 columns and pr_exc is to be calculated via a function
warning(
"Ensure the pdf you select is suitable for your data. See ??build_emap for examples of good and bad distribution choices.\n"
)
col_ids <- match(names(data)[1:2], names(output_data))
names(output_data)[col_ids] <- c("estimate", "error")
estimate <- output_data$estimate
error <- output_data$error
args_call <-
eval(do.call("substitute", list(pdflist$args, list(estimate, error))))
output_data$pr_exc <-
pdist(pname = pdflist$dist,
th = pdflist$th,
args = args_call)
}
p <- list(
output_data = output_data,
bord = bord,
bbox = bbox,
key_label = key_label,
palette = palette
)
oldClass(p) <- c("emap", class(p))
p
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.