Skip to content

Commit dfbf572

Browse files
authored
Implement usmapdata 1.0.0 changes (#51)
* Added support for Puerto Rico in map creation and transform support functions. * `us_map()` defaults to excluding Puerto Rico, but this can be changed by setting the `USMAP_EXCLUDE_PR = FALSE` environment variable. * Removed `as_sf` parameter, no longer in use anyway. * Add check results to `release` workflow artifacts with a link in the PR body template. * Updated all shapefiles (2021-2024) to include PR. closes #48 closes #49
2 parents 855b14c + f2ad7e3 commit dfbf572

33 files changed

+213
-77
lines changed

.lintr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
linters: linters_with_defaults(
2-
cyclocomp_linter = NULL,
32
line_length_linter(120),
43
object_name_linter(c("camelCase", "snake_case", "symbols"))
54
)

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Suggests:
2222
covr,
2323
dplyr,
2424
spelling,
25-
testthat (>= 3.0.0)
25+
testthat (>= 3.0.0),
26+
withr
2627
Roxygen: list(markdown = TRUE)
2728
RoxygenNote: 7.3.2
2829
Config/testthat/edition: 3

NEWS.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# [unreleased]
22

3+
### New Features
4+
* Puerto Rico has been added!
5+
* Finally, after years of procrastinating, Puerto Rico has finally been added to the map, see [Issue #48](https://github.com/pdil/usmapdata/issues/48).
6+
* All included map files have been retroactively updated to include Puerto Rico, so any valid value of `data_year` will include Puerto Rico if desired.
7+
* `us_map()` and `fips_data()` both return Puerto Rico in their data sets and it can be included or excluded just like any state (using FIPS, full name, abbreviation, etc.).
8+
* Special thanks [@dcaud](https://github.com/dcaud) who started this work [years ago](https://github.com/pdil/usmap/pull/34).
9+
10+
### Enhancements
11+
* `include` now takes precedence over `exclude` in `us_map()`.
12+
* Any items that are in both the `include` and `exclude` vectors will be _included_.
13+
14+
### Removed
15+
* The `as_sf` parameter has been completely removed from `us_map()`, `centroid_labels()`, and `fips_data()`.
16+
* It was no longer used by `usmap` nor did it have any effect if set.
17+
* Any existing code that sets it can safely delete it from `usmapdata` function calls.
18+
319
# usmapdata 0.6.0
420
Released Saturday, June 14, 2025.
521

@@ -51,7 +67,6 @@ Released Sunday, February 4, 2024.
5167
This update continues the `sf` migration by setting the `as_sf` parameter to default to the behavior of `TRUE`. This parameter no longer has any effect, as explained below. The next phase will involve updating `usmap` to no longer make use of this parameter, in which case it can be completely removed.
5268

5369
### Removed
54-
5570
* The `as_sf` parameter is now deprecated and no longer has any effect.
5671
* As part of this removal, the default behavior for `us_map()`, `centroid_labels()`, and `fips_data()` is equivalent to `as_sf = TRUE` which is to return their data as an `sf` object (see `0.2.0` release notes for more details).
5772
* This parameter will be completely removed in a future version but continues to exist for compatibility reasons.

R/create-us-map.R

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
21
#' Internal map creation tools
32
#'
43
#' @description
54
#' `create_us_map()` creates the modified shapefiles used by the
65
#' \link[usmap]{usmap} package.
76
#'
87
#' `ea_crs()` returns the US National Atlas Equal Area coordinate reference system
9-
#' (CRS) used by this package and `usmap`.
8+
#' (CRS) used by this package and \link[usmap]{usmap}.
109
#'
1110
#' `transform2D()` computes a two dimensional affine transformation matrix
1211
#' for the provided rotation angle and scale factor.
@@ -15,6 +14,8 @@
1514
#'
1615
#' `transform_hawaii()` applies the appropriate transform for the Hawaii polygons.
1716
#'
17+
#' `transform_puerto_rico()` applies the appropriate transform for the Puerto Rico polygons.
18+
#'
1819
#' `compute_centroids()` computes the modified centroids for each state or
1920
#' county polygon using a center-of-mass technique on the largest polygon in
2021
#' the region.
@@ -23,6 +24,8 @@
2324
#'
2425
#' `hawaii_bbox()` returns the bounding box of Hawaii pre-transformation.
2526
#'
27+
#' `puerto_rico_bbox()` returns the bounding box of Puerto Rico pre-transformation.
28+
#'
2629
#' @note
2730
#' Using these functions externally is not recommended since they make certain
2831
#' undocumented assumptions that may not work with all inputs.
@@ -71,10 +74,14 @@ create_us_map <- function(
7174
# FIPS code for Hawaii = 15
7275
hawaii <- transform_hawaii(us_ea[us_ea$STATEFP == "15", ])
7376

77+
# FIPS code for Puerto Rico = 72
78+
puerto_rico <- transform_puerto_rico(us_ea[us_ea$STATEFP == "72", ])
79+
7480
# keep only US states (i.e. remove territories, minor outlying islands, etc.)
75-
# also remove Alaska (02) and Hawaii (15) so that we can add in shifted one
76-
us_ea <- us_ea[!us_ea$STATEFP %in% c(as.character(57:80), "02", "15"), ]
77-
us_ea <- rbind(us_ea, alaska, hawaii)
81+
# also remove Alaska (02), Hawaii (15), Puerto Rico (72) so that we can add in
82+
# shifted versions
83+
us_ea <- us_ea[!us_ea$STATEFP %in% c(as.character(57:80), "02", "15", "72"), ]
84+
us_ea <- rbind(us_ea, alaska, hawaii, puerto_rico)
7885

7986
# delete unused columns
8087
cols <- c()
@@ -161,6 +168,16 @@ transform_hawaii <- function(hawaii) {
161168
hawaii
162169
}
163170

171+
#' @rdname create_us_map
172+
#' @keywords internal
173+
transform_puerto_rico <- function(puerto_rico) {
174+
sf::st_geometry(puerto_rico) <- sf::st_geometry(puerto_rico) * transform2D(15, 2)
175+
sf::st_geometry(puerto_rico) <- sf::st_geometry(puerto_rico) + c(-4.5e6, 4e6)
176+
sf::st_crs(puerto_rico) <- ea_crs()
177+
178+
puerto_rico
179+
}
180+
164181
#' @rdname create_us_map
165182
#' @keywords internal
166183
compute_centroids <- function(polygons, iterations = 3, initial_width_step = 10) {
@@ -264,3 +281,19 @@ hawaii_bbox <- function() {
264281
)
265282
)
266283
}
284+
285+
#' @rdname create_us_map
286+
#' @keywords internal
287+
puerto_rico_bbox <- function() {
288+
sf::st_as_sfc(
289+
sf::st_bbox(
290+
c(
291+
xmin = 3300000,
292+
xmax = 3700000,
293+
ymin = -2400000,
294+
ymax = -2200000
295+
),
296+
crs = ea_crs()
297+
)
298+
)
299+
}

R/fips-data.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#'
33
#' @inheritParams us_map
44
#'
5-
#' @return An data frame of FIPS codes of the desired \code{regions}.
5+
#' @return An data frame of FIPS codes of the desired `regions`.
66
#'
77
#' @examples
88
#' str(fips_data())
@@ -13,7 +13,6 @@
1313
#' @export
1414
fips_data <- function(
1515
regions = c("states", "state", "counties", "county"),
16-
as_sf = TRUE,
1716
data_year = NULL
1817
) {
1918
regions <- match.arg(regions)

R/us-map.R

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
11
#' Retrieve US map data
22
#'
33
#' @param regions The region breakdown for the map, can be one of
4-
#' (\code{"states"}, \code{"state"}, \code{"counties"}, \code{"county"}).
5-
#' The default is \code{"states"}.
6-
#' @param include The regions to include in the resulting map. If \code{regions} is
7-
#' \code{"states"}/\code{"state"}, the value can be either a state name, abbreviation or FIPS code.
4+
#' (`"states"`, `"state"`, `"counties"`, `"county"`).
5+
#' The default is `"states"`.
6+
#' @param include The regions to include in the resulting map. If `regions` is
7+
#' `"states"`/`"state"`, the value can be either a state name, abbreviation or FIPS code.
88
#' For counties, the FIPS must be provided as there can be multiple counties with the
99
#' same name. If states are provided in the county map, only counties in the included states
1010
#' will be returned.
11-
#' @param exclude The regions to exclude in the resulting map. If \code{regions} is
12-
#' \code{"states"}/\code{"state"}, the value can be either a state name, abbreviation or FIPS code.
11+
#' @param exclude The regions to exclude in the resulting map. If `regions` is
12+
#' `"states"`/`"state"`, the value can be either a state name, abbreviation or FIPS code.
1313
#' For counties, the FIPS must be provided as there can be multiple counties with the
14-
#' same name. The regions listed in the \code{include} parameter are applied first and the
15-
#' \code{exclude} regions are then removed from the resulting map. Any excluded regions
16-
#' not present in the included regions will be ignored.
17-
#' @param as_sf Defunct, this parameter no longer has any effect and will be removed in
18-
#' the future.
14+
#' same name. The regions listed in the `include` parameter take precedence over
15+
#' regions listed in `exclude`. If both parameters include the same region(s) they
16+
#' will be included in the map.
1917
#' @param data_year The year for which to obtain map data.
20-
#' If the value is \code{NULL}, the most recent year's data is used. If the
21-
#' provided year is not found from the available map data sets, the next most
22-
#' recent year's data is used. This can be used if an older data set is being
23-
#' plotted on the US map so that the data matches the map more accurately.
24-
#' Therefore, the provided value should match the year of the plotted data set.
25-
#' The default is \code{NULL}, i.e. the most recent available year is used.
18+
#' If the value is `NULL`, the most recent year's data is used. If the
19+
#' provided year is not found from the available map data sets, the next most
20+
#' recent year's data is used. This can be used if an older data set is being
21+
#' plotted on the US map so that the data matches the map more accurately.
22+
#' Therefore, the provided value should match the year of the plotted data set.
23+
#' The default is `NULL`, i.e. the most recent available year is used.
2624
#'
27-
#' @return An `sf` data frame of US map coordinates divided by the desired \code{regions}.
25+
#' @return An `sf` data frame of US map coordinates divided by the desired `regions`.
2826
#'
2927
#' @examples
3028
#' str(us_map())
@@ -41,7 +39,6 @@ us_map <- function(
4139
regions = c("states", "state", "counties", "county"),
4240
include = c(),
4341
exclude = c(),
44-
as_sf = TRUE,
4542
data_year = NULL
4643
) {
4744
regions <- match.arg(regions)
@@ -53,20 +50,25 @@ us_map <- function(
5350
file_path <- system.file("extdata", map_year, file_name, package = "usmapdata")
5451
df <- sf::read_sf(file_path, as_tibble = FALSE)
5552

56-
if (length(include) > 0) {
57-
df <- df[df$full %in% include |
58-
df$abbr %in% include |
59-
df$fips %in% include |
60-
substr(df$fips, 1, 2) %in% include, ]
61-
}
53+
# remove excluded items that are in `include`
54+
exclude <- setdiff(exclude, include)
6255

56+
# remove excludes
6357
if (length(exclude) > 0) {
6458
df <- df[!(df$full %in% exclude |
6559
df$abbr %in% exclude |
6660
df$fips %in% exclude |
6761
substr(df$fips, 1, 2) %in% exclude), ]
6862
}
6963

64+
# remove non-includes
65+
if (length(include) > 0) {
66+
df <- df[df$full %in% include |
67+
df$abbr %in% include |
68+
df$fips %in% include |
69+
substr(df$fips, 1, 2) %in% include, ]
70+
}
71+
7072
df[order(df$abbr), ]
7173
}
7274

@@ -75,12 +77,11 @@ us_map <- function(
7577
#' @inheritParams us_map
7678
#'
7779
#' @return An `sf` data frame of state or county centroid labels and positions
78-
#' relative to the coordinates returned by the \code{us_map} function.
80+
#' relative to the coordinates returned by the \link{us_map} function.
7981
#'
8082
#' @export
8183
centroid_labels <- function(
8284
regions = c("states", "state", "counties", "county"),
83-
as_sf = TRUE,
8485
data_year = NULL
8586
) {
8687
regions <- match.arg(regions)
@@ -109,8 +110,8 @@ available_map_years <- function() {
109110

110111
#' Select appropriate map data year from available years
111112
#'
112-
#' @param data_year The year for which to obtain \code{usmap} data.
113-
#' If the value is \code{NULL}, the most recent year is returned. If the
113+
#' @param data_year The year for which to obtain \link{us_map} data.
114+
#' If the value is `NULL`, the most recent year is returned. If the
114115
#' provided year is not found from the available map data sets, the next most
115116
#' recent available year is returned.
116117
#'

R/usmapdata-package.R

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
#' @section Map data frames:
1010
#' Alaska and Hawaii have been manually moved to a new location so that
1111
#' their new coordinates place them to the bottom-left corner of
12-
#' the map. These maps can be accessed by using the \code{\link{us_map}} function.
12+
#' the map. These maps can be accessed by using the \link{us_map} function.
1313
#'
1414
#' The function provides the ability to retrieve maps with either
15-
#' state borders or county borders using the \code{regions} parameter
15+
#' state borders or county borders using the `regions` parameter
1616
#' for convenience.
1717
#'
1818
#' States (or counties) can be included such that all other states (or counties)
19-
#' are excluded using the \code{include} parameter.
19+
#' are excluded using the `include` parameter.
2020
#'
2121
#' @author Paolo Di Lorenzo \cr
2222
#' \itemize{

data-raw/scripts/config.ini

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ cert = www2-census-gov-chain.pem
44
current_year = 2024
55
entities = state,county
66
res = 20m
7-
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Test harness script to verify map creation functions work as intended.
2+
3+
# Run from within usmapdata.Rproj
4+
devtools::load_all(getwd()) # load local developer build of usmapdata
5+
6+
usmapdata:::create_us_map(
7+
type = "counties",
8+
input_file = "data-raw/shapefiles/2024/cb_2024_us_county_20m.shp",
9+
output_dir = "data-raw/test-harness",
10+
output_file = "us_counties.gpkg"
11+
)
12+
13+
file_path <- system.file("data-raw/test-harness/us_counties.gpkg", package = "usmapdata")
14+
df <- sf::read_sf(file_path, as_tibble = FALSE)
15+
16+
ggplot2::ggplot(data = df[df$abbr == "PR", ]) +
17+
ggplot2::geom_sf(color = "black", fill = "white")
18+
19+
perform_transform <- function(data, ...) {
20+
data <- sf::st_as_sf(as.data.frame(data), coords = c("lon", "lat"))
21+
data_sf <- sf::st_as_sf(data, ...)
22+
23+
if (is.na(sf::st_crs(data_sf))) {
24+
crs <- list(...)[["crs"]]
25+
if (is.null(crs)) crs <- sf::st_crs(4326)
26+
sf::st_crs(data_sf) <- crs
27+
}
28+
29+
# Transform to canonical projection
30+
transformed <- sf::st_transform(data_sf, usmap::usmap_crs())
31+
sf::st_agr(transformed) <- "constant"
32+
33+
# Transform Alaska points
34+
ak_bbox <- usmapdata:::alaska_bbox()
35+
alaska <- sf::st_intersection(transformed, ak_bbox)
36+
alaska <- usmapdata:::transform_alaska(alaska)
37+
38+
# Transform Hawaii points
39+
hi_bbox <- usmapdata:::hawaii_bbox()
40+
hawaii <- sf::st_intersection(transformed, hi_bbox)
41+
hawaii <- usmapdata:::transform_hawaii(hawaii)
42+
43+
# Transform Hawaii points
44+
pr_bbox <- usmapdata:::puerto_rico_bbox()
45+
puerto_rico <- sf::st_intersection(transformed, pr_bbox)
46+
puerto_rico <- usmapdata:::transform_puerto_rico(puerto_rico)
47+
48+
# Re-combine all points
49+
transformed_excl_ak <- sf::st_difference(transformed, ak_bbox)
50+
sf::st_agr(transformed_excl_ak) <- "constant"
51+
52+
transformed_excl_ak_hi <- sf::st_difference(transformed_excl_ak, hi_bbox)
53+
sf::st_agr(transformed_excl_ak_hi) <- "constant"
54+
55+
transformed_excl_ak_hi_pr <- sf::st_difference(transformed_excl_ak_hi, pr_bbox)
56+
sf::st_agr(transformed_excl_ak_hi_pr) <- "constant"
57+
58+
rbind(transformed_excl_ak_hi_pr, alaska, hawaii, puerto_rico)
59+
}
60+
61+
data <- data.frame(
62+
lon = c(-74.01, -95.36, -118.24, -87.65, -134.42, -157.86, -66.104),
63+
lat = c(40.71, 29.76, 34.05, 41.85, 58.30, 21.31, 18.466),
64+
pop = c(8398748, 2325502, 3990456, 2705994, 32113, 347397, 347052)
65+
)
66+
67+
transformed_data <- perform_transform(data)
68+
69+
library(ggplot2)
70+
ggplot(data = df) +
71+
geom_sf(color = "black", fill = "white") +
72+
geom_sf(
73+
data = transformed_data,
74+
aes(size = pop),
75+
color = "red", alpha = 0.5
76+
) + usmap:::theme_map()
77+
78+
# delete map files
79+
unlink(Sys.glob("data-raw/test-harness/*.gpkg"))

inst/extdata/2021/us_counties.gpkg

20 KB
Binary file not shown.

0 commit comments

Comments
 (0)