#' Conveniently plot basic US map
#'
#' @inheritParams us_map
#' @param data A data frame containing values to plot on the map. This
#' parameter should be a data frame consisting of two columns,
#' a FIPS code (2 characters for state, 5 characters for county)
#' and the value that should be associated with that region. The
#' columns of \code{data} \emph{must} be \code{fips} or \code{state} and
#' the value of the `values` parameter.
#' @param values The name of the column that contains the values to be associated
#' with a given region. The default is \code{"value"}.
#' @param theme The theme that should be used for plotting the map. The default
#' is \code{theme_map} from \href{https://github.com/jrnold/ggthemes}{ggthemes}.
#' @param labels Whether or not to display labels on the map. Labels are not displayed
#' by default.
#' @param label_color The color of the labels to display. Corresponds to the \code{color}
#' option in the [ggplot2::aes()] mapping. The default is \code{"black"}.
#' \href{https://usmap.dev/docs/Rcolor.pdf}{Click here}
#' for more color options.
#' @param ... Other arguments to pass to [ggplot2::aes()]. These are
#' often aesthetics, used to set an aesthetic to a fixed value, like \code{color = "red"}
#' or \code{linewidth = 3}. They affect the appearance of the polygons used to render
#' the map (for example fill color, line color, line thickness, etc.). If any of
#' \code{color}/\code{colour}, \code{fill}, or \code{linewidth} are not specified they
#' are set to their default values of \code{color="black"}, \code{fill="white"},
#' and \code{linewidth=0.4}.
#'
#' @return A [ggplot2::ggplot] object that contains a basic
#' US map with the described parameters. Since the result is a \code{ggplot}
#' object, it can be extended with more [ggplot2::Geom] layers, scales, labels,
#' themes, etc.
#'
#' @seealso [usmap], [ggplot2::theme()]
#'
#' @examples
#' plot_usmap()
#' plot_usmap(regions = "states")
#' plot_usmap(regions = "counties")
#' plot_usmap(regions = "state")
#' plot_usmap(regions = "county")
#'
#' # Output is ggplot object so it can be extended
#' # with any number of ggplot layers
#' library(ggplot2)
#' plot_usmap(include = c("CA", "NV", "ID", "OR", "WA")) +
#' labs(title = "Western States")
#'
#' # Color maps with data
#' plot_usmap(data = statepop, values = "pop_2022")
#'
#' # Include labels on map (e.g. state abbreviations)
#' plot_usmap(data = statepop, values = "pop_2022", labels = TRUE)
#' # Choose color for labels
#' plot_usmap(data = statepop, values = "pop_2022", labels = TRUE, label_color = "white")
#'
#' @importFrom rlang .data
#' @export
plot_usmap <- function(regions = c("states", "state", "counties", "county"),
include = c(),
exclude = c(),
data = data.frame(),
values = "values",
theme = theme_map(),
labels = FALSE,
label_color = "black",
...) {
# check for ggplot2
if (!requireNamespace("ggplot2", quietly = TRUE)) {
stop("`ggplot2` must be installed to use `plot_usmap`.
Use: install.packages(\"ggplot2\") and try again.")
}
.data <- ggplot2::.data
# parse parameters
regions <- match.arg(regions)
geom_args <- list(...)
# set geom_polygon defaults
if (is.null(geom_args[["colour"]]) && is.null(geom_args[["color"]])) {
geom_args[["color"]] <- "black"
}
if (is.null(geom_args[["linewidth"]])) {
geom_args[["linewidth"]] <- 0.4
}
# set default "fill" if data is not included
if (is.null(geom_args[["fill"]]) && nrow(data) == 0) {
geom_args[["fill"]] <- "white"
}
# create polygon layer
if (nrow(data) == 0) {
map_df <- usmap::us_map(regions = regions, include = include, exclude = exclude)
geom_args[["mapping"]] <- ggplot2::aes()
} else {
map_df <- usmap::map_with_data(data, values = values, include = include, exclude = exclude)
if (!is.null(map_df$county)) regions <- "counties"
geom_args[["mapping"]] <- ggplot2::aes(fill = .data[[values]])
}
polygon_layer <- do.call(ggplot2::geom_sf, geom_args)
# create label layer
if (labels) {
if (regions == "state") regions <- "states"
else if (regions == "county") regions <- "counties"
centroid_labels <- usmapdata::centroid_labels(regions)
if (length(include) > 0) {
centroid_labels <- centroid_labels[
centroid_labels$full %in% include |
centroid_labels$abbr %in% include |
centroid_labels$fips %in% include,
]
}
if (length(exclude) > 0) {
centroid_labels <- centroid_labels[!(
centroid_labels$full %in% exclude |
centroid_labels$abbr %in% exclude |
centroid_labels$fips %in% exclude |
substr(centroid_labels$fips, 1, 2) %in% exclude
), ]
}
if (regions == "county" || regions == "counties") {
label_layer <- ggplot2::geom_sf_text(
data = centroid_labels,
ggplot2::aes(label = sub(" County", "", .data$county)),
color = label_color
)
} else {
label_layer <- ggplot2::geom_sf_text(
data = centroid_labels,
ggplot2::aes(label = .data$abbr), color = label_color
)
}
} else {
label_layer <- ggplot2::geom_blank()
}
# construct final plot
ggplot2::ggplot(data = map_df) + polygon_layer + label_layer + theme
}
#' Convenient theme map
#'
#' @description
#' This creates a nice map theme for use in [plot_usmap()].
#' It originated from the `ggthemes` package located at this repository:
#' \url{https://github.com/jrnold/ggthemes}.
#'
#' This function was manually rewritten here to avoid the need for
#' another package import.
#'
#' @keywords internal
theme_map <- function(base_size = 9, base_family = "") {
element_blank <- ggplot2::element_blank()
`%+replace%` <- ggplot2::`%+replace%` # nolint: object_name_linter
unit <- ggplot2::unit
ggplot2::theme_bw(base_size = base_size, base_family = base_family) %+replace%
ggplot2::theme(axis.line = element_blank,
axis.text = element_blank,
axis.ticks = element_blank,
axis.title = element_blank,
panel.background = element_blank,
panel.border = element_blank,
panel.grid = element_blank,
panel.spacing = unit(0, "lines"),
plot.background = element_blank,
legend.position = "inside",
legend.justification.inside = c(0, 0))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.