#' Plot a Geographic Map
#'
#' Creates a map with a table as input, using shading to represent the values of
#' countries or states on the map.
#'
#' @inherit Column
#' @param x A matrix, two-dimensional array, table or vector, containing the
#' data to be plotted. The \code{\link{rownames}} (or \code{\link{names}} in
#' the case of a vector) should contain the names of the geographic entities
#' to be plotted.
#' @param country Character string optionally stating the country that the states are from, if
#' \code{map.type} is \code{"states"}.
#' @param high.resolution Specifically request a high resolution map. Otherwise
#' the resolution of the map is chosen automatically based on the resolution required
#' for the requested countries or regions.
#' @param show.missing.regions Logical; Whether to plot regions not included in
#' \code{x} with values of \code{NA}. Used only by \code{"leaflet"}.
#' @param treat.NA.as.0 Plots any \code{NA} values in the data and any
#' geographical entities without data as having a zero value.
#' @param colors A vector of two colors, which are used as endpoints in
#' interpolating colors.
#' @param ocean.color The color used for oceans (or background).
#' @param color.NA The color used to represent missing values. Not used when
#' \code{treat.NA.as.0}, is set to missing.
#' @param global.font.family Character; font family for all occurrences of any
#' font attribute for the chart unless specified individually.
#' @param global.font.color Global font color as a named color in character format
#' (e.g. "black") or an rgb value (e.g. #' rgb(0, 0, 0, maxColorValue = 255)).
#' @param legend.title The text to appear above the legend.
#' @param values.hovertext.format A string representing a d3 formatting code.
#' See https://github.com/d3/d3/blob/master/API.md#number-formats-d3-format
#' @param values.bounds.minimum Numeric; specifies the minimum value in the colorscale.
#' If not specified, this will be automatically determined from the data.
#' If the value specified is larger than the minimum in the data then
#' the specified value will be ignored.
#' @param values.bounds.maximum Numeric; specifies the maximum value in the colorscale.
#' @param mapping.package Either \code{"leaflet"} (better graphics, wider range of
#' maps) or \code{"plotly"} (faster).
#' @param background If \code{"mapping.package"} is \code{"leaflet"}, add a background
#' tile from opensteetmaps.
#' @param zip.country One of \code{"Automatic"}, \code{"USA"}, \code{"UK"} or \code{"Australia"}.
#' If \code{"Automatic"} an attempt is made to infer the country from the data.
#' @param legend.show Logical; Whether to display a legend with the color scale.
#' @param legend.font.family Font family of legend.
#' @param legend.font.color Font color of legend. Only used with \code{plotly} object.
#' @param legend.font.size Font size of legend. Changing the defaults for leaflet object can give strange spacing.
#' @param hovertext.font.size Only used with \code{plotly} object.
#' @return an HTML widget for \code{"leaflet"} or a \code{"plotly"} object.
#' @examples
#' data <- seq(4)
#' names(data) <- c("France", "China", "Brazil", "Canada")
#' GeographicMap(data)
#' @importFrom verbs Sum
#' @export
GeographicMap <- function(x,
country,
high.resolution = FALSE,
show.missing.regions = TRUE,
treat.NA.as.0 = FALSE,
colors = c("#CCF3FF", "#23B0DB"),
ocean.color = "#DDDDDD",
opacity = 1,
color.NA = "#808080",
global.font.family = "Arial",
global.font.color = "#2C2C2C",
legend.show = TRUE,
legend.title = "",
legend.font.family = global.font.family,
legend.font.color = global.font.color,
legend.font.size = 14,
values.hovertext.format = "",
values.bounds.minimum = NULL,
values.bounds.maximum = NULL,
mapping.package = "leaflet",
background = FALSE,
title = "",
title.font.family = global.font.family,
title.font.color = global.font.color,
title.font.size = 16,
subtitle = "",
subtitle.font.family = global.font.family,
subtitle.font.color = global.font.color,
subtitle.font.size = 12,
footer = "",
footer.font.family = global.font.family,
footer.font.color = global.font.color,
footer.font.size = 8,
footer.wrap = TRUE,
footer.wrap.nchar = 100,
hovertext.font.family = global.font.family,
hovertext.font.size = 11,
zip.country = "Automatic")
{
requireNamespace("sp")
values.bounds.minimum <- charToNumeric(values.bounds.minimum)
values.bounds.maximum <- charToNumeric(values.bounds.maximum)
if (isPercentData(x) && isAutoFormat(values.hovertext.format))
values.hovertext.format <- paste0(values.hovertext.format, "%")
if (values.hovertext.format == ".0")
values.hovertext.format <- "~.0f"
if (grepl("[0-9]$", values.hovertext.format))
values.hovertext.format <- paste0(values.hovertext.format, "f")
if (values.hovertext.format == "%")
values.hovertext.format <- ".0%"
table <- cleanMapInput(checkMatrixNames(x))
# Find map.type from rownames
names <- tolower(rownames(table))
# Get default parameter values
if (is.null(hovertext.font.family))
hovertext.font.family <- global.font.family
if (is.null(legend.font.family))
legend.font.family <- global.font.family
if (length(legend.font.size) == 0)
legend.font.size <- 14
if (length(hovertext.font.size) == 0)
hovertext.font.size <- 11
if (is.null(opacity))
opacity <- if (mapping.package == "leaflet" && background) 0.5 else 1.0
if (mapping.package == "leaflet")
color.warning <- "Alpha values in selected colors were not used in color scale. Adjust 'opacity' instead"
else
color.warning <- "Alpha values in colors for Geographic Map with plotly are ignored."
colors <- StripAlphaChannel(colors)
# Check for defined formats first, or if country or zip.country are specified.
map.type <- definedFormatMapTypes(names, zip.country)
if (!missing(country) && country != "")
{
map.type <- "states"
country <- tidyCountryName(country)
}
if (map.type == "unknown")
{
types <- list(regions = c("northeast", "midwest", "south", "west"),
continents = c("africa", "asia", "europe", "north america", "oceania", "south america"),
aus_areas = tolower(australia.areas$name),
countries = tolower(CountriesOrContinents("country")))
match.counts <- lapply(types, function(x) length(intersect(x, names)))
country <- FindCountryFromRegions(names)
match.counts[["states"]] <- attr(country, "matches")
if (max(unlist(match.counts)) == 0)
stop("No rows of the input data were matched with geographic entity names.")
map.type <- names(which.max(match.counts))
}
if (grepl("postcode", map.type, fixed = TRUE))
rownames(table) <- tidyPostcodes(names, map.type)
# Get the coordinate and name data
if (map.type == "countries" || map.type == "continents")
{
# Getting geographic boundaries. If the user asks for high resolution maps
# or any of the requested regions are missing in the low resolution map, use
# the 1:50m map, otherwise use the 1:110m map.
req.names <- rownames(table)
if (high.resolution || any(req.names %in% missing110))
{
coords <- map.coordinates.50
}
else
{
coords <- map.coordinates.110
}
coords <- coords[!(coords$continent %in% "Antarctica"), ]
remove.regions <- "Antarctica"
name.map <- admin0.name.map.by.admin
}
else if (map.type == "states")
{
coords <- subset(admin1.coordinates, admin1.coordinates$admin == country)
name.map <- admin1.name.map[[country]]
map.type <- country
remove.regions <- NULL
}
else if (map.type == "regions")
{
coords <- subset(admin1.coordinates, admin1.coordinates$admin == "United States of America")
name.map <- admin1.name.map[["United States of America"]]
remove.regions <- NULL
states <- coords[["name"]] # updated table to states
regions <- us.regions$Region[match(states, us.regions$State)]
table <- table[match(tolower(regions), tolower(rownames(table))), , drop = FALSE]
rownames(table) <- states
}
else if (map.type == "aus_postcodes")
{
coords <- australia.postcodes
remove.regions <- name.map <- NULL
}
else if (map.type == "us_postcodes")
{
coords <- us.postcodes
remove.regions <- name.map <- NULL
}
else if (map.type == "uk_postcodes")
{
coords <- uk.postcodes
remove.regions <- name.map <- NULL
}
else if (map.type == "aus_areas")
{
coords <- australia.areas
remove.regions <- NULL
name.map <- australiaAreasNameMap()
}
else
stop("Unrecognized map.type")
if (treat.NA.as.0)
table[is.na(table)] <- 0
statistic <- attr(table, "statistic", exact = TRUE)
if (is.null(statistic))
statistic <- ""
# Fix unmatched names
if (!is.null(name.map))
{
correct.all <- names(name.map)
for (correct in correct.all)
{
incorrect <- setdiff(name.map[[correct]], correct.all)
matches <- match(tolower(incorrect), tolower(rownames(table)))
if (!all(is.na(matches)))
rownames(table)[matches[!is.na(matches)]] <- correct
}
}
structure <- switch(map.type, continents = "continent", countries = "admin", "name")
coords[[structure]] <- as.character(coords[[structure]])
if (!is.null(remove.regions) && remove.regions != "")
{
remove.regions <- str_trim(unlist(strsplit(remove.regions, ",", fixed = TRUE)))
if (!is.null(name.map))
{
for (region in names(name.map))
{
alt <- name.map[[region]]
matches <- match(alt, remove.regions)
if (!all(is.na(matches)))
remove.regions[matches[!is.na(matches)]] <- region
}
}
coords <- coords[!(coords[[structure]] %in% remove.regions), ]
table <- table[!(rownames(table) %in% remove.regions), , drop = FALSE]
}
coords.names <- tolower(coords[[structure]])
incorrect.names <- !tolower(rownames(table)) %in% coords.names
n.unmatched.names <- Sum(incorrect.names)
if (n.unmatched.names > 0.75 * nrow(table))
warning(paste0(n.unmatched.names, " rows of the input data were not matched with",
" geographic entity names. Please check that the data you are plotting is one of:",
" countries; states of a country; continents; US regions; or US, UK or Australian zip codes."))
if (any(incorrect.names))
{
msg <- paste("Unmatched region names:", paste(rownames(table)[incorrect.names], collapse = ", "))
warning(msg)
}
if (all(incorrect.names) && zip.country != "Automatic")
stop("No names in the data were matched to zip codes in your selected country.")
table <- table[!incorrect.names, , drop = FALSE]
table.names <- rownames(table)
# Splicing data onto coordinate data.frame.
country.lookup <- match(coords.names, tolower(table.names))
categories <- colnames(table)
n.categories <- length(categories)
if (mapping.package == "plotly" && n.categories > 1)
{
n.categories <- 1
table <- table[, 1, drop = FALSE]
warning("Only the first series will be shown when package is 'plotly'. Change to 'leaflet' to show multiple series.")
}
for (i in 1:n.categories)
{
new.var <- table[country.lookup, i]
if(treat.NA.as.0)
new.var[is.na(new.var)] <- 0
coords$table <- new.var
names(coords)[ncol(coords)] <- paste("table", i, sep = "")
}
# Creating a variable for use in scaling the legend.
min.value <- min(table, na.rm = TRUE)
if (treat.NA.as.0)
min.value <- min(0, min.value)
coords$table.max <- if(NCOL(table) != 1 && mapping.package != "plotly")
apply(table, 1, function(x) ifelse(!all(is.na(x)), max(x, na.rm = TRUE), NA))[country.lookup]
else
table[, 1][country.lookup]
if (treat.NA.as.0)
coords$table.max[is.na(coords$table.max)] <- 0
min.in.table.max <- min(coords$table.max , na.rm = TRUE)
if (min.value < min.in.table.max) #Replacing the minimum with the global minimum.
coords$table.max[match(min.in.table.max, coords$table.max)] <- min.value
max.range <- max(coords$table.max, na.rm = TRUE)
# Remove regions not in input data
if (!show.missing.regions)
coords <- coords[!is.na(country.lookup), ]
# Decide formatting for hovertext
if (values.hovertext.format == "" && grepl("%)?$", statistic))
values.hovertext.format <- ".0%"
if (percentFromD3(values.hovertext.format))
{
format.function <- FormatAsPercent
decimals <- decimalsFromD3(values.hovertext.format, 0)
mult <- 100
suffix <- "%"
}
else
{
format.function <- FormatAsReal
decimals <- decimalsFromD3(values.hovertext.format, 2)
mult <- 1
suffix <- ""
}
if (!is.null(values.bounds.minimum) && values.bounds.minimum > min.value)
warning("Minimum value must be smaller than ", min.value, ".")
if (!is.null(values.bounds.maximum) && values.bounds.maximum < max.range)
warning("Maximum value must be larger than ", max.range, ".")
values.bounds.minimum <- min(values.bounds.minimum, min.value)
values.bounds.maximum <- max(values.bounds.maximum, max.range)
legend.show <- setShowLegend(legend.show)
# Pass all data to a function specific to the package
if (mapping.package == "leaflet") {
map <- leafletMap(coords, colors, opacity, values.bounds.minimum, values.bounds.maximum,
color.NA, legend.show, legend.title, legend.font.family,
legend.font.color, legend.font.size, mult, decimals, suffix,
values.hovertext.format, treat.NA.as.0, n.categories, categories,
format.function, map.type, background, ocean.color,
hovertext.font.family, hovertext.font.size, show.missing.regions)
} else
{
# mapping.package == "plotly"
map <- plotlyMap(table, name.map, colors, opacity, values.bounds.minimum,
values.bounds.maximum, color.NA, legend.show,
legend.title, mult, decimals, suffix, values.hovertext.format,
treat.NA.as.0, n.categories, categories, format.function, map.type,
ocean.color, high.resolution, title, subtitle, footer,
legend.font = list(family=legend.font.family, color=legend.font.color, size=legend.font.size),
title.font = list(family=title.font.family, color=title.font.color, size=title.font.size),
subtitle.font = list(family=subtitle.font.family, color=subtitle.font.color, size=subtitle.font.size),
footer.font = list(family=footer.font.family, color=footer.font.color, size=footer.font.size),
footer.wrap = footer.wrap, footer.wrap.nchar = footer.wrap.nchar,
hovertext.font.family, hovertext.font.size)
}
result <- list(htmlwidget = map)
class(result) <- "StandardChart"
attr(result, "ChartType") <- "Filled Map"
result
}
# Helper function to plot the leaflet map
#' @importFrom leaflet leaflet colorNumeric addLegend labelFormat highlightOptions addPolygons
#' @importFrom leaflet addLayersControl layersControlOptions setView fitBounds addTiles tileOptions
#' @importFrom sp proj4string spTransform
#' @importFrom stats as.formula
#' @importFrom htmltools browsable tagList tags htmlDependency
leafletMap <- function(coords, colors, opacity, min.value, max.range, color.NA,
legend.show, legend.title, legend.font.family,
legend.font.color, legend.font.size,
mult, decimals, suffix, values.hovertext.format,
treat.NA.as.0, n.categories, categories, format.function, map.type,
background, ocean.color, hovertext.font.family, hovertext.font.size,
show.missing.regions)
{
coords.with.values <- which(!is.na(coords$table.max))
max.values <- unique(coords$table.max[coords.with.values])
if (length(max.values) == 1)
max.values <- c(max.values, max.values * 1.1)
# If we are close to the anti meridian, wrap coords and polygons
wrap.antimeridian <- FALSE
if ("longitude" %in% colnames(coords@data) && map.type != "United States of America" &&
map.type != "regions") {
lng <- coords@data$longitude
if (any(lng > 170)) {
wrap.antimeridian <- TRUE
.wrapAntiMeridian <- function(x) ifelse(x < 0, 360 + x, x)
coords@data$longitude <- .wrapAntiMeridian(lng)
for (i in 1:length(coords@polygons)) {
n.poly <- length(coords@polygons[[i]]@Polygons)
for (j in 1:n.poly) {
coords@polygons[[i]]@Polygons[[j]]@coords[,1] <- .wrapAntiMeridian(coords@polygons[[i]]@Polygons[[j]]@coords[,1])
coords@polygons[[i]]@Polygons[[j]]@labpt[1] <- .wrapAntiMeridian(coords@polygons[[i]]@Polygons[[j]]@labpt[1])
}
coords@polygons[[i]]@labpt[1] <- .wrapAntiMeridian(coords@polygons[[i]]@labpt[1])
}
}
}
# Creating the map
map <- leaflet(coords)
# Attribution requires background, which may be transparent
attribution <- switch(map.type, aus_postcodes = "Based on ABS data",
aus_areas = "Based on ABS data",
uk_postcodes = "<a href='www.opendoorlogistics.com'>opendoorlogistics.com</a>",
"")
map <- addTiles(map, attribution = attribution, options = tileOptions(opacity = as.numeric(background)))
#opacity <- 1
.pal <- colorNumeric(palette = colors, domain = c(min.value, max.range),
na.color = color.NA)
.rev.pal <- colorNumeric(palette = colors, domain = c(min.value, max.range),
na.color = color.NA, reverse = TRUE)
if (legend.show)
{
map <- addLegend(map, "bottomright", pal = .rev.pal, values = c(max.values, min.value),
title = legend.title,
# reverse label ordering so high values are at top
labFormat = labelFormat(transform = function(x) sort(x * mult, decreasing = TRUE),
digits = 3, # seems to work like an upper bound
suffix = suffix,
big.mark = ifelse(commaFromD3(values.hovertext.format), ",", "")),
opacity = opacity,
na.label = ifelse(treat.NA.as.0, "0", "NA"))
}
highlight.options <- highlightOptions(weight = 5, color = "#666",
fillOpacity = 0.7,
bringToFront = TRUE)
# Add an outline of USA to fill gaps in zip code areas
if (map.type == "us_postcodes" && show.missing.regions)
{
country <- "United States of America"
# suppress warnings caused by sp update from PROJ4 to PROJ6
suppressWarnings(country.coords <- spTransform(map.coordinates.50[map.coordinates.50$name == country, ],
proj4string(coords)))
country.coords$color <- ifelse(treat.NA.as.0, 0, NA)
map <- addPolygons(map, stroke = FALSE, smoothFactor = 0.2,
fillOpacity = opacity, fillColor = ~.pal(country.coords$color),
data = country.coords)
}
## DS-4143: When plotting U.S.A. regions, override hover text so that
## it displays U.S. region names instead of state names
if (map.type == "regions" && !anyNA(idx <- match(coords$name, us.regions[["State"]])))
location.label <- as.character(us.regions[["Region"]][idx])
else
location.label <- coords$name
if (n.categories == 1)
{
map <- addPolygons(map, stroke = FALSE, smoothFactor = 0.2,
fillOpacity = opacity, fillColor = ~.pal(coords$table1),
highlightOptions = highlight.options,
label = paste0(location.label, ": ", format.function(coords$table1,
decimals = decimals,
comma.for.thousands = commaFromD3(values.hovertext.format))))
categoryControls <- ""
}
else
{
for (i in 1:n.categories)
{
cl <- as.formula(paste("~.pal(table", i, ")", sep = ""))
map <- addPolygons(map, stroke = FALSE, smoothFactor = 0.2,
fillOpacity = opacity, color = cl, group = categories[i],
highlightOptions = highlight.options,
label = paste0(location.label, ": ",
format.function(coords[[paste("table", i, sep = "")]],
decimals = decimals,
comma.for.thousands = commaFromD3(values.hovertext.format))))
categoryControls <- paste0("
document.querySelector('.leaflet-control-layers-expanded').style.backgroundColor = 'transparent';
document.querySelector('.leaflet-control-layers-expanded').style.border = 'none';
document.querySelector('.leaflet-control-layers-expanded').style.color = '", legend.font.color, "';")
}
map <- addLayersControl(map, baseGroups = categories,
options = layersControlOptions(collapsed = FALSE))
}
# Centre on the contiguous states, avoiding Alaska and Hawaii
# This is for state and regional maps, not postcodes
if (map.type == "United States of America" || map.type == "regions") {
map <- setView(map, -96, 37.8, zoom = 4)
} else if (wrap.antimeridian) {
# Manually set zoom level to fit to modified coords
lng <- coords@data$longitude
ltd <- coords@data$latitude
lng.rng <- range(lng, na.rm = TRUE)
ltd.rng <- range(ltd, na.rm = TRUE)
map <- fitBounds(map, lng.rng[1], ltd.rng[1], lng.rng[2], ltd.rng[2])
}
# Make legend semi-opaque if background is used to make it easier to read
panel.bg <- if (background) 'rgba(220,220,220,0.4)' else 'transparent'
# old versions of Geo. Map Standard R could pass NULL for this
if (is.null(ocean.color))
ocean.color <- formals(GeographicMap)$ocean.color
if (is.null(legend.font.color))
legend.font.color <- formals(GeographicMap)$global.font.color
if (is.null(legend.font.family))
legend.font.family <- formals(GeographicMap)$global.font.family
if (is.null(legend.font.size))
legend.font.size <- formals(GeographicMap)$legend.font.size
## Read in custom css, modify user-specified values,
## write to temp. file, and add it as a dependency of the widget
## Note, this could also be achieved (less robustly) using
## htmlwidgets::prependContent(map, "<style>...</style>")
css <- readLines(system.file("assets", "css", "leaflet-custom.css",
package = "flipStandardCharts"))
for (var in c("panel.bg", "ocean.color", "legend.font.color",
"legend.font.family", "legend.font.size"))
css <- sub(paste0("/[*]", var, "[*]/"), get(var), css)
tf <- tempfile(fileext = ".css")
writeLines(css, con = tf)
dep <- htmlDependency(
name = "displayr-leaflet-css",
version = "0.0.1",
src = c(file = file.path(dirname(tf))),
stylesheet = basename(tf),
# attachment = basename(tf),
all_files = FALSE
)
# As of leaflet version 2.2.0, HTML dependencies for leaflet() are included
# in the dependencies item of the htmlwidget
ndeps <- length(map$dependencies)
if (ndeps == 0)
map$dependencies <- list(dep)
else
map$dependencies[[ndeps + 1]] <- dep
return(map)
}
# Helper function to plot the plotly map
#' @importFrom plotly plot_geo colorbar
plotlyMap <- function(table, name.map, colors, opacity, min.value, max.range, color.NA, legend.show,
legend.title, mult, decimals, suffix, values.hovertext.format,
treat.NA.as.0, n.categories, categories, format.function, map.type,
ocean.color, high.resolution, title, subtitle, footer,
legend.font, title.font, subtitle.font, footer.font,
footer.wrap, footer.wrap.nchar, hovertext.font.family, hovertext.font.size)
{
df <- data.frame(table)
df <- df[!is.na(df[, 1]), , drop = FALSE] # avoid warning for NA
lataxis <- NULL
if (map.type == "countries")
{
locationmode <- "country names"
lataxis <- list(range = c(-55, 75))
scope <- "world"
if (treat.NA.as.0) # add rows of zeros for missing countries
{
missing.countries <- names(name.map)[!tolower(names(name.map)) %in% tolower(rownames(df))]
zeros.matrix <- matrix(rep(0, length(missing.countries) * ncol(df)), ncol = ncol(df))
colnames(zeros.matrix) <- colnames(df)
rownames(zeros.matrix) <- missing.countries
df <- rbind(df, zeros.matrix)
}
}
else if (map.type == "United States of America" || map.type == "regions")
{
locationmode <- "USA-states"
lataxis <- NULL
scope <- "usa"
# Convert names to 2 letter state codes required by plotly
for (full.state.name in names(name.map))
{
all.state.names <- c(full.state.name, name.map[[full.state.name]])
matches <- match(tolower(all.state.names), tolower(rownames(df)))
if (!all(is.na(matches)))
rownames(df)[matches[!is.na(matches)]] <- all.state.names[nchar(all.state.names) == 2]
else if (treat.NA.as.0) # add row of zeros for this state
{
df <- rbind(df, rep(0, ncol(df)))
rownames(df)[nrow(df)] <- all.state.names[nchar(all.state.names) == 2]
}
}
}
else
stop("Only world and USA state or region maps are available with 'plotly' package.",
" Change to 'leaflet' to map other types.")
if (treat.NA.as.0) # set NA color to zero color
{
color.zero <- colorRamp(colors)(0 - min(0, min.value) / (max.range - min(0, min.value)))
color.NA <- rgb(color.zero, maxColorValue = 255)
}
line.color <- rgb(0.4, 0.4, 0.4, alpha = opacity)
bdry <- list(color = rgb(0.4,0.4,0.4, alpha = opacity), width = 0) # no boundary line between shaded regions
# specify map projection/options
g <- list(
scope = scope,
showframe = FALSE,
showcoastlines = TRUE,
showland = opacity == 1.0, # color will show through transparency
landcolor = color.NA,
showcountries = TRUE,
coastlinecolor = if (ocean.color == color.NA) line.color else ocean.color,
coastlinewidth = 0.25,
countrycolor = line.color,
countrywidth = 0.25,
subunitcolor = line.color,
subunitwidth = 0.25,
showocean = opacity == 1.0,
oceancolor = ocean.color,
showlakes = opacity == 1.0,
lakecolor = ocean.color,
projection = list(type = 'Mercator'),
resolution = ifelse(high.resolution, 50, 110),
lataxis = lataxis,
bgcolor = ocean.color)
p <- plot_geo(df, locationmode = locationmode)
## DS-4143: When plotting U.S.A. regions, plotly recognizes state names,
## but hovertext should use region names if that's what the user has supplied
hover.text <- format.function(df[, 1], decimals = decimals,
comma.for.thousands = commaFromD3(values.hovertext.format))
hover.info <- "location+text"
if (map.type == "regions" && scope == "usa")
{
regions <- us.regions[["Region"]][match(rownames(df), us.regions[["Code"]])]
hover.text <- paste0(regions, " - ", hover.text)
hover.info <- "text"
}
p <- add_trace(p, hoverinfo = hover.info,
z = df[, 1],
zmin = min.value,
zmax = max.range,
color = df[, 1],
colors = rgb(t(col2rgb(colors)),maxColorValue = 255, alpha = opacity), # opacity ignored by plotly
locations = rownames(df),
text = hover.text,
marker = list(line = bdry)
)
if (legend.show)
p <- colorbar(p, title = legend.title, x = 1, y = 0.5, yanchor = "middle",
outlinewidth = 0, ypad = 0,
tickfont = legend.font, titlefont = legend.font,
tickformat = values.hovertext.format,
separatethousands = commaFromD3(values.hovertext.format))
else
p <- hide_colorbar(p)
footer <- autoFormatLongLabels(footer, footer.wrap, footer.wrap.nchar, truncate=FALSE)
margins <- list(l = 0, r = 0, t = 10, b = 0, pad = 0)
margins <- setMarginsForText(margins, title, subtitle, footer,
title.font$size, subtitle.font$size, footer.font$size)
p <- config(p, displayModeBar = FALSE)
p$sizingPolicy$browser$padding <- 0
p <- layout(p, geo = g, margin = margins,
annotations = list(setSubtitle(subtitle, subtitle.font, margins),
setTitle(title, title.font, margins),
setFooter(footer, footer.font, margins)),
hoverlabel = list(namelength = -1, bordercolor = "transparent",
font = list(family = hovertext.font.family, color = "white",
size = hovertext.font.size)),
paper_bgcolor = 'transparent'
)
p
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.