Showing preview only (7,103K chars total). Download the full file or copy to clipboard to get everything.
Repository: walkerke/tigris
Branch: master
Commit: 07e457d1902d
Files: 114
Total size: 6.8 MB
Directory structure:
gitextract_yatmm7b4/
├── .Rbuildignore
├── .github/
│ ├── .gitignore
│ ├── FUNDING.yml
│ └── workflows/
│ └── R-CMD-check.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── NAMESPACE
├── NEWS
├── R/
│ ├── enumeration_units.R
│ ├── fips_codes.R
│ ├── geocode.R
│ ├── helpers.R
│ ├── landmarks.R
│ ├── legislative.R
│ ├── metro_areas.R
│ ├── national.R
│ ├── native.R
│ ├── places.R
│ ├── pumas.R
│ ├── shift_geometry.R
│ ├── states.R
│ ├── tigris-package.R
│ ├── transportation.R
│ ├── utils.R
│ ├── water.R
│ └── zzz.R
├── README.md
├── data/
│ └── fips_codes.rda
├── data-raw/
│ ├── national_county.txt
│ ├── prep-zip-lookup.R
│ ├── prep_codes.R
│ ├── state.txt
│ └── zcta_county_rel_10.txt
├── man/
│ ├── address_ranges.Rd
│ ├── alaska_native_regional_corporations.Rd
│ ├── append_geoid.Rd
│ ├── area_water.Rd
│ ├── block_groups.Rd
│ ├── blocks.Rd
│ ├── call_geolocator.Rd
│ ├── call_geolocator_latlon.Rd
│ ├── coastline.Rd
│ ├── combined_statistical_areas.Rd
│ ├── congressional_districts.Rd
│ ├── core_based_statistical_areas.Rd
│ ├── counties.Rd
│ ├── county_subdivisions.Rd
│ ├── divisions.Rd
│ ├── erase_water.Rd
│ ├── filter_place.Rd
│ ├── filter_state.Rd
│ ├── fips_codes.Rd
│ ├── geo_join.Rd
│ ├── grep_place.Rd
│ ├── grep_state.Rd
│ ├── is_tigris.Rd
│ ├── landmarks.Rd
│ ├── linear_water.Rd
│ ├── list_counties.Rd
│ ├── list_places.Rd
│ ├── list_states.Rd
│ ├── load_tiger.Rd
│ ├── load_tiger_doc_template.Rd
│ ├── lookup_code.Rd
│ ├── metro_divisions.Rd
│ ├── military.Rd
│ ├── nation.Rd
│ ├── native_areas.Rd
│ ├── new_england.Rd
│ ├── places.Rd
│ ├── primary_roads.Rd
│ ├── primary_secondary_roads.Rd
│ ├── pumas.Rd
│ ├── rails.Rd
│ ├── rbind_tigris.Rd
│ ├── regions.Rd
│ ├── roads.Rd
│ ├── school_districts.Rd
│ ├── shift_geometry.Rd
│ ├── state_legislative_districts.Rd
│ ├── states.Rd
│ ├── tigris-exports.Rd
│ ├── tigris-package.Rd
│ ├── tigris_cache_dir.Rd
│ ├── tigris_type.Rd
│ ├── tracts.Rd
│ ├── tribal_block_groups.Rd
│ ├── tribal_census_tracts.Rd
│ ├── tribal_subdivisions_national.Rd
│ ├── urban_areas.Rd
│ ├── validate_county.Rd
│ ├── validate_state.Rd
│ ├── voting_districts.Rd
│ └── zctas.Rd
├── tests/
│ ├── testthat/
│ │ ├── _snaps/
│ │ │ ├── enumeration_units.md
│ │ │ └── landmarks.md
│ │ ├── test-enumeration_units.R
│ │ ├── test-geocode.R
│ │ ├── test-landmarks.R
│ │ ├── test-legislative.R
│ │ ├── test-lookup_helper.R
│ │ ├── test-metro_areas.R
│ │ ├── test-national.R
│ │ ├── test-native.R
│ │ ├── test-places.R
│ │ ├── test-pumas.R
│ │ ├── test-shift_geometry.R
│ │ ├── test-states.R
│ │ ├── test-transportation.R
│ │ ├── test-water.R
│ │ └── test_lookup_helper.R
│ └── testthat.R
└── tigris.Rproj
================================================
FILE CONTENTS
================================================
================================================
FILE: .Rbuildignore
================================================
^.*\.Rproj$
^\.Rproj\.user$
^data-raw$
^\.travis\.yml$
^tigris\.Rcheck$
^tigris.*\.tar\.gz$
^tigris.*\.tgz$
^img$
^\.github$
================================================
FILE: .github/.gitignore
================================================
*.html
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: walkerke
custom: https://paypal.me/walkerdata
================================================
FILE: .github/workflows/R-CMD-check.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
push:
branches: [main, master]
pull_request:
name: R-CMD-check.yaml
permissions: read-all
jobs:
R-CMD-check:
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
strategy:
fail-fast: false
matrix:
config:
- {os: macos-latest, r: 'release'}
- {os: windows-latest, r: 'release'}
- {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'}
- {os: ubuntu-latest, r: 'release'}
- {os: ubuntu-latest, r: 'oldrel-1'}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
R_KEEP_PKG_SOURCE: yes
steps:
- uses: actions/checkout@v4
- uses: r-lib/actions/setup-pandoc@v2
- uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.config.r }}
http-user-agent: ${{ matrix.config.http-user-agent }}
use-public-rspm: true
- uses: r-lib/actions/setup-r-dependencies@v2
with:
extra-packages: any::rcmdcheck
needs: check
- uses: r-lib/actions/check-r-package@v2
with:
upload-snapshots: true
build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'
================================================
FILE: .gitignore
================================================
.Rproj.user
.Rhistory
.RData
.Ruserdata
tigris.Rcheck/
tigris*.tar.gz
tigris*.tgz
================================================
FILE: DESCRIPTION
================================================
Package: tigris
Type: Package
Title: Load Census TIGER/Line Shapefiles
Version: 2.2.1.9000
Date: 2025-07-18
Authors@R: c(
person(given="Kyle", family="Walker", email="kyle@walker-data.com", role=c("aut", "cre")),
person(given="Bob", family="Rudis", email="bob@rudis.net", role="ctb"),
person(given="Eli", family="Pousson", email="Eli.Pousson@baltimorecity.gov", role="ctb")
)
URL: https://github.com/walkerke/tigris
BugReports: https://github.com/walkerke/tigris/issues
Description: Download TIGER/Line shapefiles from the United States Census Bureau
(<https://www.census.gov/geographies/mapping-files/time-series/geo/tiger-line-file.html>)
and load into R as 'sf' objects.
License: MIT + file LICENSE
LazyData: TRUE
Encoding: UTF-8
Depends:
R (>= 3.3.0)
Suggests:
testthat (>= 3.0.0),
ggplot2,
ggthemes,
leaflet,
knitr,
tidycensus,
sp,
withr
Imports:
stringr,
magrittr,
utils,
rappdirs,
httr,
uuid,
sf,
dplyr,
methods,
cli,
rlang
Config/testthat/edition: 3
RoxygenNote: 7.3.2
Roxygen: list(markdown = TRUE)
================================================
FILE: LICENSE
================================================
YEAR: 2016
COPYRIGHT HOLDER: Kyle Walker
================================================
FILE: NAMESPACE
================================================
# Generated by roxygen2: do not edit by hand
export("%>%")
export(address_ranges)
export(alaska_native_regional_corporations)
export(append_geoid)
export(area_water)
export(block_groups)
export(blocks)
export(call_geolocator)
export(call_geolocator_latlon)
export(coastline)
export(combined_statistical_areas)
export(congressional_districts)
export(core_based_statistical_areas)
export(counties)
export(county_subdivisions)
export(divisions)
export(erase_water)
export(filter_place)
export(filter_state)
export(geo_join)
export(grep_place)
export(grep_state)
export(is_tigris)
export(landmarks)
export(linear_water)
export(list_counties)
export(list_places)
export(list_states)
export(lookup_code)
export(metro_divisions)
export(military)
export(nation)
export(native_areas)
export(new_england)
export(places)
export(primary_roads)
export(primary_secondary_roads)
export(pumas)
export(rails)
export(rbind_tigris)
export(regions)
export(roads)
export(school_districts)
export(shift_geometry)
export(state_legislative_districts)
export(states)
export(tigris_cache_dir)
export(tigris_type)
export(tracts)
export(tribal_block_groups)
export(tribal_census_tracts)
export(tribal_subdivisions_national)
export(urban_areas)
export(validate_county)
export(validate_state)
export(voting_districts)
export(zctas)
import(dplyr)
import(httr)
import(rappdirs)
import(rlang)
import(sf)
import(utils)
import(uuid)
importFrom(cli,cli_abort)
importFrom(cli,cli_inform)
importFrom(cli,cli_warn)
importFrom(dplyr,mutate)
importFrom(httr,GET)
importFrom(httr,stop_for_status)
importFrom(magrittr,"%>%")
importFrom(methods,as)
importFrom(stringr,str_pad)
importFrom(stringr,str_trim)
importFrom(utils,URLencode)
================================================
FILE: NEWS
================================================
tigris development
-------------------------------------------------------
* Add `{rlang}` and `{cli}` packages to Imports. Add `{withr}` to Suggests.
* Warn users when `filter_by` contains multiple geometries and only part of the filter can be used.
* Export `validate_state()` and `validate_county()` functions with added `multiple` argument to allow validation of multiple states or counties in a single call.
* Expand test coverage.
tigris 2.2.1
-------------------------------------------------------
* Functions now default to a year of 2024.
* Error handling incorporated into the package; downloads that fail over HTTP will try the FTP site before failing entirely.
* FTP downloads can be requested with the argument protocol = "ftp" or by setting the option options(tigris_protocol = "ftp").
* Various bug fixes and performance improvements.
tigris 2.0
-------------------------------------------------------
* A new filter_by argument allows users to subset datasets by a bounding box or another sf object when requesting data.
* Deprecation of formal support for sp classes and removal of associated dependencies (rgdal, rgeos, maptools)
* Functions in tigris now default to a year of 2021.
tigris 1.6
-------------------------------------------------------
* All functions in tigris now default to a year of 2020. Different years can be requested
with the year argument.
* A new function, erase_water(), automatically erases water area from an input polygon dataset
to improve cartographic display.
tigris 1.5
-------------------------------------------------------
* tigris now correctly supports 2020 US Census shapefiles across its functions.
* An updated voting_districts() function retrieves voting districts to assist with redistricting analyses.
* National cartographic boundary files for Census tracts, block groups, places, PUMAs, state legislative districts, school districts, and voting districts are now available.
tigris 1.4
-------------------------------------------------------
* The new function shift_geometry() will shift and optionally rescale features in Alaska, Hawaii, and Puerto Rico for better thematic mapping of the United States. See ?shift_geometry for more details.
* 2020 geographies are available (TIGER/Line only) by specifying the argument year = 2020.
* Various bug fixes and improvements; thanks to Maria Paula Caldas and Mark Richards for submitting pull requests.
tigris 1.0
-------------------------------------------------------
* As of version 1.0 (released in July 2020), tigris functions return simple features objects with a default year of 2019.
tigris 0.6
-------------------------------------------------------
* You are now able to specify a custom cache directory for your data. To set the cache directory, use the new `tigris_cache_dir()` function.
* tigris now defaults to the 2016 TIGER/Line and cartographic boundary shapefiles.
* Thanks to contributors from Transport Foundry (https://github.com/transportfoundry), tigris now includes some geolocator functions.
tigris 0.5.1
-------------------------------------------------------
* tigris now downloads data to a temporary directory rather than creating a cache directory by default to conform with CRAN policies. To enable caching of data, set `options(tigris_use_cache = TRUE)` in your R script or .Rprofile.
* 2000 and 2010 Zip Code Tabulation Areas (ZCTAs) are now available.
tigris 0.5
-------------------------------------------------------
* tigris now will return objects of class 'sf' if requested by the user with the argument `class = 'sf'` or by setting the option `options(tigris_class = 'sf')`.
* Historical states, counties, Census tracts, and block groups are now available going back to 1990
* In the event of a download error, tigris will attempt to re-download without the user having to request it.
* Various improvements and bug fixes.
tigris 0.3.3
-------------------------------------------------------
* tigris now accommodates county name changes in the 2015 TIGER/Line dataset. Shannon County, SD (FIPS code 113) is now Oglala Lakota County (FIPS code 102), and Wade Hampton Census Area, AK (FIPS code 270) is now Kusilvak Census Area (FIPS code 158).
* fixed a bug that would counties not to load in non-interactive mode
tigris 0.3
-------------------------------------------------------
* tigris now defaults to the 2015 TIGER/Line shapefiles and cartographic boundary shapefiles, the most recent shapefiles available from the US Census Bureau.
tigris 0.2.2
-------------------------------------------------------
* New function, `voting_districts()`, enables users to retrieve voting district (electoral precinct) shapefiles from the 2012 TIGER/Line dataset.
* tigris now imports and re-exports the `plot()` function from the sp package so that Census shapefiles can be plotted without having to load sp explicitly.
tigris 0.2
-------------------------------------------------------
* Enhancements to the geo_join function to merge tabular data frames to spatial data frames. An optional parameter, by, allows you to supply one column name to merge on if the column names are the same.
* geo_join also accommodates inner joins as well. By supplying 'inner' to the new how parameter, the resultant spatial data frame will retain only those rows that match the target tabular data frame.
* Various improvements and bug fixes.
================================================
FILE: R/enumeration_units.R
================================================
#' Download a US Counties shapefile into R, and optionally subset by state
#'
#' Description from the US Census Bureau (see link for source):
#' The primary legal divisions of most states are termed counties. In Louisiana,
#' these divisions are known as parishes. In Alaska, which has no counties,
#' the equivalent entities are the organized boroughs, city and boroughs,
#' municipalities, and census areas; the latter of which are delineated
#' cooperatively for statistical purposes by the state of Alaska and the
#' Census Bureau. In four states (Maryland, Missouri, Nevada, and Virginia),
#' there are one or more incorporated places that are independent of any county
#' organization and thus constitute primary divisions of their states. These
#' incorporated places are known as independent cities and are treated as
#' equivalent entities for purposes of data presentation. The District of
#' Columbia and Guam have no primary divisions, and each area is considered
#' an equivalent entity for purposes of data presentation. All of the counties
#' in Connecticut and Rhode Island and nine counties in Massachusetts were
#' dissolved as functioning governmental entities; however, the Census Bureau
#' continues to present data for these historical entities in order to provide
#' comparable geographic units at the county level of the geographic hierarchy
#' for these states and represents them as nonfunctioning legal entities in
#' data products. The Census Bureau treats the following entities as
#' equivalents of counties for purposes of data presentation: municipios in
#' Puerto Rico, districts and islands in American Samoa, municipalities in the
#' Commonwealth of the Northern Mariana Islands, and islands in the U.S.
#' Virgin Islands. Each county or statistically equivalent entity is assigned
#' a three-character numeric Federal Information Processing Series (FIPS) code
#' based on alphabetical sequence that is unique within state and an
#' eight-digit National Standard feature identifier.
#'
#' @param state The two-digit FIPS code (string) of the state you want, or a
#' vector of codes if you want multiple states. Can also be state name
#' or state abbreviation.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' counties file. Defaults to FALSE (the most detailed TIGER file).
#' @param resolution The resolution of the cartographic boundary file (if cb == TRUE).
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#'
#' @export
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch4GARM.pdf}
#' @examples \dontrun{
#' library(tigris)
#' library(ggplot2)
#'
#' me <- counties("Maine", cb = TRUE)
#'
#' gg <- ggplot()
#' gg <- gg + geom_sf(data = me, color="black",
#' fill="white", size=0.25)
#' gg
#' }
counties <- function(
state = NULL,
cb = FALSE,
resolution = '500k',
year = NULL,
...
) {
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
cyear <- as.character(year)
if (cb == TRUE) {
if (year %in% c(1990, 2000)) {
suf <- substr(as.character(year), 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/PREVGENZ/co/co%sshp/co99_d%s_shp.zip",
suf,
suf
)
} else if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_050_00_%s.zip",
resolution
)
} else {
if (year > 2013) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_county_%s.zip",
cyear,
cyear,
resolution
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/cb_%s_us_county_%s.zip",
cyear,
cyear,
resolution
)
}
}
} else {
if (year == 1990)
stop("Please specify `cb = TRUE` to get 1990 data.", call. = FALSE)
if (year %in% c(2000, 2010)) {
suf <- substr(cyear, 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/COUNTY/%s/tl_2010_us_county%s.zip",
cyear,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/COUNTY/tl_%s_us_county.zip",
cyear,
cyear
)
}
}
ctys <- load_tiger(url, tigris_type = "county", ...)
state <- unlist(sapply(state, validate_state, USE.NAMES = FALSE))
if (!is.null(state)) {
ctys <- ctys[ctys$STATEFP %in% state, ]
}
# Dissolve polygons for 1990 and 2000 CB
if (cb && year %in% c(1990, 2000)) {
sclass <- class(ctys)
if (!any(sclass == "sf")) {
ctys <- st_as_sf(ctys)
}
if (year == 1990) {
ctys <- ctys %>%
mutate(id = paste0(.data$ST, .data$CO)) %>%
group_by(.data$id) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
ST = first(.data$ST),
CO = first(.data$CO),
CO99_D90_ = first(.data$CO99_D90_),
CO99_D90_I = first(.data$CO99_D90_I),
NAME = first(.data$NAME),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
select(-.data$id) %>%
st_cast("MULTIPOLYGON")
} else if (year == 2000) {
ctys <- ctys %>%
mutate(id = paste0(.data$STATE, .data$COUNTY)) %>%
group_by(.data$id) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
STATE = first(.data$STATE),
COUNTY = first(.data$COUNTY),
CO99_D00_ = first(.data$CO99_D00_),
CO99_D00_I = first(.data$CO99_D00_I),
NAME = first(.data$NAME),
LSAD = first(.data$LSAD),
LSAD_TRANS = first(.data$LSAD_TRANS),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
select(-.data$id) %>%
st_cast("MULTIPOLYGON")
}
if (any(sclass == "SpatialPolygonsDataFrame")) {
ctys <- as(ctys, "Spatial")
}
}
attr(ctys, 'tigris') <- 'county'
return(ctys)
}
#' Download a Census tracts shapefile into R, and optionally subset by county
#'
#' Description from the US Census Bureau (see link for source):
#' Census Tracts are small, relatively permanent statistical subdivisions of
#' a county or equivalent entity that are updated by local participants prior
#' to each decennial census as part of the Census Bureau's Participant
#' Statistical Areas Program. The Census Bureau delineates census tracts in
#' situations where no local participant existed or where state, local, or
#' tribal governments declined to participate. The primary purpose of census
#' tracts is to provide a stable set of geographic units for the presentation
#' of statistical data.
#'
#' Census tracts generally have a population size between 1,200 and 8,000 people,
#' with an optimum size of 4,000 people. A census tract usually covers a
#' contiguous area; however, the spatial size of census tracts varies widely
#' depending on the density of settlement. Census tract boundaries are
#' delineated with the intention of being maintained over a long time so that
#' statistical comparisons can be made from census to census. Census tracts
#' occasionally are split due to population growth or merged as a result of
#' substantial population decline.
#'
#' Census tract boundaries generally follow visible and identifiable features.
#' They may follow nonvisible legal boundaries, such as minor civil division
#' (MCD) or incorporated place boundaries in some states and situations, to
#' allow for census-tract-to-governmental-unit relationships where the
#' governmental boundaries tend to remain unchanged between censuses. State and
#' county boundaries always are census tract boundaries in the standard census
#' geographic hierarchy.
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of Census tracts will be returned for
#' years 2019 and later.
#' @param county The three-digit FIPS code (string) of the county you'd like to
#' subset for, or a vector of FIPS codes if you desire multiple counties.
#' Can also be a county name or vector of names.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' tracts file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @param resolution The resolution of the cartographic boundary file (if using cb = TRUE).
#' Defaults to '500k'; the other option is '5m' (1:5 million). Resolution of '5m' is #' only available for the national Census tract file for years 2022 and later.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch10GARM.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' tarrant <- tracts("TX", "Tarrant", cb = TRUE)
#'
#' leaflet(tarrant) %>%
#' addTiles() %>%
#' addPolygons(popup = ~NAME)
#' }
tracts <- function(
state = NULL,
county = NULL,
cb = FALSE,
resolution = "500k",
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (
(resolution == "5m" && year < 2022) |
(resolution == "5m" && !is.null(state))
) {
stop(
"`resolution = '5m'` for Census tracts is only available for the national Census tract CB file in years 2022 and later.",
call. = FALSE
)
}
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message("Retrieving Census tracts for the entire United States")
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
if (cb == TRUE) {
if (year %in% c(1990, 2000)) {
suf <- substr(as.character(year), 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/PREVGENZ/tr/tr%sshp/tr%s_d%s_shp.zip",
suf,
state,
suf
)
} else if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_%s_140_00_500k.zip",
state
)
} else {
if (year > 2013) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_tract_%s.zip",
as.character(year),
as.character(year),
state,
resolution
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/cb_%s_%s_tract_500k.zip",
as.character(year),
as.character(year),
state
)
}
}
} else {
if (year == 1990)
stop("Please specify `cb = TRUE` to get 1990 data.", call. = FALSE)
if (year %in% c(2000, 2010)) {
cyear <- as.character(year)
suf <- substr(cyear, 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/TRACT/%s/tl_2010_%s_tract%s.zip",
cyear,
state,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TRACT/tl_%s_%s_tract.zip",
as.character(year),
as.character(year),
state
)
}
}
trcts <- load_tiger(url, tigris_type = "tract", ...)
if (!is.null(county)) {
county <- sapply(county, function(x) {
validate_county(state, x)
})
trcts <- trcts[trcts$COUNTYFP %in% county, ]
}
# Dissolve polygons for 1990 and 2000 CB
if (cb && year %in% c(1990, 2000)) {
sclass <- class(trcts)
if (!any(sclass == "sf")) {
trcts <- st_as_sf(trcts)
}
if (year == 1990) {
trcts <- trcts %>%
mutate(
TRACTSUF = ifelse(
is.na(.data$TRACTSUF),
"00",
.data$TRACTSUF
)
) %>%
mutate(
id = paste0(
.data$ST,
.data$CO,
.data$TRACTBASE,
.data$TRACTSUF
)
) %>%
group_by(.data$id) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
ST = first(.data$ST),
CO = first(.data$CO),
TRACTBASE = first(.data$TRACTBASE),
TRACTSUF = first(.data$TRACTSUF),
TRACT_NAME = first(.data$TRACT_NAME),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
select(-.data$id) %>%
st_cast("MULTIPOLYGON")
} else if (year == 2000) {
trcts <- trcts %>%
mutate(TRACT = str_pad(.data$TRACT, 6, "right", "0")) %>%
mutate(id = paste0(.data$STATE, .data$COUNTY, .data$TRACT)) %>%
group_by(.data$id) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
STATE = first(.data$STATE),
COUNTY = first(.data$COUNTY),
TRACT = first(.data$TRACT),
NAME = first(.data$NAME),
LSAD = first(.data$LSAD),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
select(-.data$id) %>%
st_cast("MULTIPOLYGON")
}
if (any(sclass == "SpatialPolygonsDataFrame")) {
trcts <- as(trcts, "Spatial")
}
}
attr(trcts, "tigris") <- "tract"
return(trcts)
}
#' Download a school district shapefile into R
#'
#' From the US Census Bureau (see link for source):
#' School Districts are single-purpose administrative units within which local officials provide public
#' educational services for the area's residents. The Census Bureau obtains school district boundaries,
#' names, local education agency codes, grade ranges, and school district levels biennially from state
#' education officials. The Census Bureau collects this information for the primary purpose of providing the
#' U.S. Department of Education with annual estimates of the number of children in poverty within each
#' school district, county, and state. This information serves as the basis for the Department of Education to
#' determine the annual allocation of Title I funding to states and school districts.
#'
#' The Census Bureau creates pseudo-unified school districts for areas in which unified school districts do
#' not exist. Additionally, elementary and secondary school districts do not exist in all states.
#' Please see the link for more information on how the Census Bureau creates the school district shapefiles.
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of school districts will be returned for
#' years 2019 and later.
#' @param type Specify whether you want to return a unified school district (the default, \code{'unified'}),
#' an elementary school district (\code{'elementary'}), or a secondary school district (\code{'secondary'}).
#' Please note: elementary and secondary school districts do not exist in all states
#' @param cb if TRUE, download a generalized (1:500k)
#' school districts file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' schools <- school_districts("Maine")
#'
#' leaflet(schools) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5)
#' }
school_districts <- function(
state = NULL,
type = 'unified',
cb = FALSE,
year = NULL,
...
) {
if (is.null(year)) {
year = getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message("Retrieving school districts for the entire United States")
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (type == 'unified') {
type <- 'unsd'
} else if (type == 'elementary') {
type <- 'elsd'
} else if (type == 'secondary') {
type <- 'scsd'
} else {
stop(
"Invalid school district type. Valid types are 'unified', 'elementary', and 'secondary'.",
call. = FALSE
)
}
cyear <- as.character(year)
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_%s_500k.zip",
cyear,
cyear,
state,
type
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/%s/tl_%s_%s_%s.zip",
cyear,
toupper(type),
cyear,
state,
type
)
}
return(load_tiger(url, tigris_type = type, ...))
}
#' Download a Census block groups shapefile into R, and optionally subset by county
#'
#' Description from the US Census Bureau (see link for source):Standard block groups are clusters of
#' blocks within the same census tract that have the same first digit of
#' their 4-character census block number. For example, blocks 3001, 3002, 3003..., 3999 in census tract
#' 1210.02 belong to Block Group 3. Due to boundary and feature changes that occur throughout the
#' decade, current block groups do not always maintain these same block number to block group
#' relationships. For example, block 3001 might move due to a census tract boundary change but the block
#' number will not change, even if it does not still fall in block group 3. However, the GEOID for that block,
#' identifying block group 3, would remain the same in the attribute information in the TIGER/Line Shapefiles
#' because block GEOIDs are always built using the decennial geographic codes.
#'
#' Block groups delineated for the 2010 Census generally contain between 600 and 3,000 people. Most
#' block groups were delineated by local participants in the Census Bureau's Participant Statistical Areas
#' Program (PSAP). The Census Bureau delineated block groups only where a local or tribal government
#' declined to participate or where the Census Bureau could not identify a potential local participant.
#'
#' A block group usually covers a contiguous area. Each census tract contains at least one block group and
#' block groups are uniquely numbered within census tract. Within the standard census geographic
#' hierarchy, block groups never cross county or census tract boundaries, but may cross the boundaries of
#' county subdivisions, places, urban areas, voting districts, congressional districts, and American Indian,
#' Alaska Native, and Native Hawaiian areas.
#'
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of block groups will be returned for
#' years 2019 and later.
#' @param county The three-digit FIPS code (string) of the county you'd like to
#' subset for, or a vector of FIPS codes if you desire multiple counties.
#' Can also be a county name or vector of names.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' benton_bgs <- block_groups("Oregon", "Benton")
#'
#' plot(benton_bgs$geometry)
#' }
block_groups <- function(
state = NULL,
county = NULL,
cb = FALSE,
year = NULL,
...
) {
if (is.null(year)) {
year = getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
cyear <- as.character(year)
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message(
"Retrieving Census block groups for the entire United States"
)
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
if (cb == TRUE) {
if (year %in% c(1990, 2000)) {
suf <- substr(as.character(year), 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/PREVGENZ/bg/bg%sshp/bg%s_d%s_shp.zip",
suf,
state,
suf
)
} else if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_%s_150_00_500k.zip",
state
)
} else {
if (year > 2013) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_bg_500k.zip",
cyear,
cyear,
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/cb_%s_%s_bg_500k.zip",
cyear,
cyear,
state
)
}
}
} else {
if (year == 1990)
stop("Please specify `cb = TRUE` to get 1990 data.", call. = FALSE)
if (year %in% c(2000, 2010)) {
suf <- substr(cyear, 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/BG/%s/tl_2010_%s_bg%s.zip",
cyear,
state,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/BG/tl_%s_%s_bg.zip",
cyear,
cyear,
state
)
}
}
bgs <- load_tiger(url, tigris_type = "block_group", ...)
if (!is.null(county)) {
county <- sapply(county, function(x) {
validate_county(state, x)
})
bgs <- bgs[bgs$COUNTYFP %in% county, ]
}
# Dissolve polygons for 1990 and 2000 CB
if (cb && year %in% c(1990, 2000)) {
sclass <- class(bgs)
if (!any(sclass == "sf")) {
bgs <- st_as_sf(bgs)
}
if (year == 1990) {
bgs <- bgs %>%
group_by(.data$GEOID) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
ST = first(.data$ST),
CO = first(.data$CO),
TRACT = first(.data$TRACT),
BG = first(.data$BG),
AREALAND = first(.data$AREALAND),
AREAWAT = first(.data$AREAWAT),
AREATOT = first(.data$AREATOT),
NAME = first(.data$NAME),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
st_cast("MULTIPOLYGON")
} else if (year == 2000) {
bgs <- bgs %>%
mutate(TRACT = str_pad(.data$TRACT, 6, "right", "0")) %>%
mutate(
id = paste0(
.data$STATE,
.data$COUNTY,
.data$TRACT,
.data$BLKGROUP
)
) %>%
group_by(.data$id) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
STATE = first(.data$STATE),
COUNTY = first(.data$COUNTY),
TRACT = first(.data$TRACT),
BLKGROUP = first(.data$BLKGROUP),
NAME = first(.data$NAME),
LSAD = first(.data$LSAD),
LSAD_TRANS = first(.data$LSAD_TRANS),
COUNTYFP = first(.data$COUNTYFP),
STATEFP = first(.data$STATEFP)
) %>%
select(-.data$id) %>%
st_cast("MULTIPOLYGON")
}
if (any(sclass == "SpatialPolygonsDataFrame")) {
bgs <- as(bgs, "Spatial")
}
}
attr(bgs, "tigris") <- "block_group"
return(bgs)
}
#' Download a Zip Code Tabulation Area (ZCTA) shapefile into R
#'
#' ZIP Code Tabulation Areas (ZCTAs) are generalized areal representations of
#' United States Postal Service (USPS) ZIP Code service areas. Please see the link provided for
#' information on how the Census Bureau creates ZCTAs, and for important information on the
#' differences between ZCTAs and ZIP Codes.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' ZCTA file. Defaults to FALSE (the most detailed TIGER/Line file).
#' \strong{A warning:} the detailed TIGER/Line ZCTA file is massive
#' (around 502MB unzipped), and the generalized version is also large
#' (64MB zipped). Be prepared for this especially if you have a slower
#' internet connection.
#' @param starts_with Character vector specifying the beginning digits of the
#' ZCTAs you want to return. For example, supplying the argument
#' \code{starts_with = c("75", "76")} will return only those ZCTAs that begin
#' with 75 or 76. Defaults to NULL, which will return all ZCTAs in the US.
#' @param state the state for which you are requesting data; only available for 2000 (TIGER/Line
#' and CB shapefiles) and 2010 (TIGER/Line shapefiles only)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www.census.gov/programs-surveys/geography/guidance/geo-areas/zctas.html}
#' @export
#' @examples \dontrun{
#' # Example: get ZCTAs that intersect the Memphis, TN urbanized area
#'
#' library(tigris)
#' zcta1 <- zctas(cb = TRUE, starts_with = c("37", "38", "72"))
#'
#' uas <- urban_areas()
#'
#' memphis_ua <- uas[grep("Memphis", uas$NAME10), ]
#'
#' mem_zcta <- zcta1[memphis_ua, ]
#'
#' plot(mem_zcta$geometry)
#'
#' }
zctas <- function(
cb = FALSE,
starts_with = NULL,
year = NULL,
state = NULL,
...
) {
if (is.null(year)) {
year = getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year > 2020 && cb) {
stop(
sprintf(
"The Census Bureau has not yet released the CB ZCTA file for %s. Please use the argument `year = 2020` or `cb = FALSE` instead.",
year
),
call. = FALSE
)
}
if (!is.null(state) && year > 2010) {
stop("ZCTAs are only available by state for 2000 and 2010.")
}
if (!is.null(state) && year == 2010 && cb == TRUE) {
stop(
"ZCTAs are only available by state for 2010 when cb = FALSE.",
call. = FALSE
)
}
if (year == 1990) {
stop(
"Zip Code Tabulation Areas are only available beginning with the 2000 Census.",
call. = FALSE
)
}
if (!is.null(state)) state <- validate_state(state)
cache <- getOption("tigris_use_cache")
if (is.null(cache)) {
message(
"ZCTAs can take several minutes to download. To cache the data and avoid re-downloading in future R sessions, set `options(tigris_use_cache = TRUE)`"
)
}
cyear <- as.character(year)
if (cb) {
if (year == 2000) {
if (is.null(state)) {
url <- "https://www2.census.gov/geo/tiger/PREVGENZ/zt/z500shp/zt99_d00_shp.zip"
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/PREVGENZ/zt/z500shp/zt%s_d00_shp.zip",
state
)
}
} else if (year == 2010) {
url <- "https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_860_00_500k.zip"
} else if (year >= 2020) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_zcta520_500k.zip",
cyear,
cyear
)
} else if (year < 2020) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_zcta510_500k.zip",
cyear,
cyear
)
if (year == 2013) url <- gsub("shp/", "", url)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_zcta520_500k.zip",
cyear,
cyear
)
}
} else {
if (year >= 2020) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/ZCTA520/tl_%s_us_zcta520.zip",
cyear,
cyear
)
} else {
if (year %in% c(2000, 2010)) {
suf <- substr(cyear, 3, 4)
if (is.null(state)) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/ZCTA5/%s/tl_2010_us_zcta5%s.zip",
cyear,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/ZCTA5/%s/tl_2010_%s_zcta5%s.zip",
cyear,
state,
suf
)
}
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/ZCTA5/tl_%s_us_zcta510.zip",
cyear,
cyear
)
}
}
}
zcta <- load_tiger(url, tigris_type = "zcta", ...)
# Handle split ZCTAs in 2000 CB file
if (year == 2000 && cb) {
warning(
"CB ZCTAs for 2000 include separate polygons for discontiguous parts.\nCombine by summarizing over the ZCTA column; this can be a time-consuming operation."
)
}
if (!is.null(starts_with)) {
nms <- names(zcta)
col <- grep("ZCTA", nms)
if (length(starts_with) > 1) {
tmp <- sapply(starts_with, function(x) paste0("^", x))
zcta <- zcta[grep(paste(tmp, collapse = "|"), zcta[[col]]), ]
} else {
zcta <- zcta[grep(paste0("^", starts_with), zcta[[col]]), ]
}
}
attr(zcta, "tigris") <- "zcta"
return(zcta)
}
#' Download a Census block shapefile into R
#'
#' Description from the US Census Bureau (see link for source): Census blocks are statistical areas
#' bounded on all sides by visible features, such as streets, roads,
#' streams, and railroad tracks, and by non-visible boundaries such as city, town, township, and county
#' limits, and short line-of-sight extensions of streets and roads. Generally, census blocks are small in area;
#' for example, a block in a city. Census blocks in suburban and rural areas may be large, irregular and
#' bounded by a variety of features, such as roads, streams, and/or transmission line rights-of-way. In
#' remote areas census blocks may encompass hundreds of square miles. Census blocks cover all territory
#' in the United States, Puerto Rico, and the Island areas. Blocks do not cross the boundaries of any entity
#' for which the Census Bureau tabulates data.
#'
#' This function will download an entire block shapefile for a selected state
#' into R, and optionally subset by county. \strong{A warning:} Census block
#' shapefiles are often very large, especially for large states - for example, the
#' block file for Texas is 462MB zipped! If you have a slow or unreliable internet
#' connection, or insufficient memory, this may prove burdensome given that you
#' have to first download by state and then subset.
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation.
#' @param county The three-digit FIPS code (string) of the county you'd like to
#' subset for, or a vector of FIPS codes if you desire multiple counties.
#' Can also be a county name or vector of names.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' # Simple example using Rose Island, American Samoa
#' # Be careful with Census blocks for states!
#'
#' library(tigris)
#' library(leaflet)
#'
#' rose_island <- blocks(state = "AS", county = "Rose Island")
#'
#' leaflet(rose_island) %>%
#' addTiles() %>%
#' addPolygons()
#'
#' }
blocks <- function(state, county = NULL, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (length(county) > 1 && year < 2011) {
p <- lapply(county, function(x) {
blocks(state = state, county = x, year = year, ...)
}) %>%
rbind_tigris()
return(p)
}
if (year < 2000) {
fname <- as.character(match.call())[[1]]
msg <- "Block data are not available for 1990."
stop(msg, call. = FALSE)
}
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
cyear <- as.character(year)
if (year >= 2014) {
if (year >= 2020) {
# New block logic for 2020
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TABBLOCK20/tl_%s_%s_tabblock20.zip",
cyear,
cyear,
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TABBLOCK/tl_%s_%s_tabblock10.zip",
cyear,
cyear,
state
)
}
} else if (year %in% 2011:2013) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TABBLOCK/tl_%s_%s_tabblock.zip",
cyear,
cyear,
state
)
} else if (year %in% c(2000, 2010)) {
suf <- substr(cyear, 3, 4)
if (!is.null(county)) {
county <- validate_county(state, county)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/TABBLOCK/%s/tl_2010_%s%s_tabblock%s.zip",
cyear,
state,
county,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/TABBLOCK/%s/tl_2010_%s_tabblock%s.zip",
cyear,
state,
suf
)
}
} else {
stop()
}
blks <- load_tiger(url, tigris_type = "block", ...)
if (!is.null(county) && year > 2010) {
if (year >= 2020) {
county <- sapply(county, function(x) {
validate_county(state, x)
})
blks <- blks[blks$COUNTYFP20 %in% county, ]
} else {
county <- sapply(county, function(x) {
validate_county(state, x)
})
blks <- blks[blks$COUNTYFP10 %in% county, ]
}
}
attr(blks, "tigris") <- "block"
return(blks)
}
#' Download a county subdivision shapefile into R
#'
#' From the US Census Bureau (see link for source, and more information): "All counties and
#' statistically equivalent entities consist of one or more geographic units that the Bureau
#' of the Census recognizes as county subdivisions. The two major types of county subdivisions
#' are minor civil divisions(MCDs) and census county divisions (CCDs).
#' A State has either MCDs or their statistical equivalents, or CCDs; it cannot
#' contain both."
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation.
#' @param county The three-digit FIPS code (string) of the county you'd like to
#' subset for, or a vector of FIPS codes if you desire multiple counties.
#' Can also be a county name or vector of names.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch8GARM.pdf}
#' @export
#'
#' @examples \dontrun{
#' library(tigris)
#'
#' or <- county_subdivisions('Oregon', c('Linn', 'Benton'))
#'
#' plot(or$geometry)
#'
#' }
county_subdivisions <- function(
state,
county = NULL,
cb = FALSE,
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2010) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2010.",
fname
)
stop(msg, call. = FALSE)
}
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
cyear <- as.character(year)
if (cb == TRUE) {
if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_%s_060_00_500k.zip",
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_cousub_500k.zip",
cyear,
cyear,
state
)
if (year == 2013) url <- gsub("shp/", "", url)
}
} else {
if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/COUSUB/2010/tl_2010_%s_cousub10.zip",
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/COUSUB/tl_%s_%s_cousub.zip",
cyear,
cyear,
state
)
}
}
cs <- load_tiger(url, tigris_type = "county_subdivision", ...)
if (!is.null(county)) {
county <- sapply(county, function(x) {
validate_county(state, x)
})
cs <- cs[cs$COUNTYFP %in% county, ]
}
attr(cs, "tigris") <- "county_subdivision"
return(cs)
}
================================================
FILE: R/fips_codes.R
================================================
#' Dataset with FIPS codes for US states and counties
#'
#' Built-in dataset for use with the \code{lookup_code} function.
#' To access the data directly, issue the command \code{data(fips_codes)}.
#' @title Dataset with FIPS codes for US states and counties
#' @description Built-in dataset for use with the \code{lookup_code} function.
#' To access the data directly, issue the command \code{data(fips_codes)}.
#'
#' \itemize{
#' \item \code{county}: County name, title-case
#' \item \code{county_code}: County code. (3-digit, 0-padded, character)
#' \item \code{state}: Upper-case abbreviation of state
#' \item \code{state_code}: State FIPS code (2-digit, 0-padded, character)
#' \item \code{state_name}: Title-case name of state
#' }
#'
#' @docType data
#' @keywords datasets
#' @name fips_codes
#'
#' @usage data(fips_codes)
#' @note Last updated 2023-05-18
#' @format A data frame with 3,256 rows and 5 variables
"fips_codes"
================================================
FILE: R/geocode.R
================================================
#' Retrieve GEOID from the Census Geocoder by address
#'
#' Returns GEOID for 2020 geographies.
#'
#' @param address A tibble/data frame with (at a minimum, others can be present)
#' either character columns street, city, and state OR numeric columns lat and
#' lon. Lat/lon columns take priority.
#' @param geoid_type GEOID level to return, \code{c('county', 'tract', 'block group', 'block')}.
#' Defaults to block.
#' @return the original tibble with GEOIDs appended as a new column called
#' \code{geoid}.
#'
#' @author Josie Kressner, \email{josie@@transportfoundry.com}
#'
#' @importFrom dplyr mutate
#' @export
#' @examples \dontrun{
#' airports <- dplyr::data_frame(
#' street = "700 Catalina Dr", city = "Daytona Beach", state = "FL"
#' )
#' append_geoid(airports, 'tract')
#' }
append_geoid <- function(address, geoid_type = 'block') {
if ("lat" %in% colnames(address) && "lon" %in% colnames(address)) {
# Call for each row of the data
geoids <- vector(mode="character", length = nrow(address))
for (i in 1:nrow(address)) {
geoids[i] <- call_geolocator_latlon(address$lat[i], address$lon[i])
}
} else {
# If street, city, or state columns are factors, convert them
# Call for each row of the data
geoids <- vector(mode="character", length = nrow(address))
for (i in 1:nrow(address)) {
geoids[i] <- call_geolocator(
as.character(address$street[i]),
as.character(address$city[i]),
as.character(address$state[i])
)
}
}
# Append onto database
address <- dplyr::mutate(address, geoid = geoids)
# AABBBCCCCCCDEEE
if (geoid_type == 'county') {
end <- 5
} else if (geoid_type == 'tract') {
end <- 11
} else if (geoid_type == 'block group') {
end <- 12
} else {
end <- 15
}
address <- dplyr::mutate(address,
geoid = ifelse(is.na(.data$geoid), NA_character_, substr(.data$geoid, 1, end)))
return(address)
}
#' Call geolocator for one address
#'
#' @param street A character string indicating a street name and number
#' @param city A character string indicating a city
#' @param state A two-digit character string with a state postal code
#' @param zip A five-digit character string with a postal zip code. Optional parameter.
#'
#' @return A character string representing the Census block of the supplied
#' address.
#'
#' importFrom utils URLencode
#' importFrom httr GET stop_for_status
#'
#' @export
#'
call_geolocator <- function(street, city, state, zip = NA) {
call_start <- "https://geocoding.geo.census.gov/geocoder/geographies/address?"
if(is.na(zip)){
# Build url when zip is default/NA
url <- paste0(
"street=", utils::URLencode(street),
"&city=", utils::URLencode(city),
"&state=", state
)}
if(!is.na(zip)){
# Build url when zip is not default/NA
if(inherits(zip, "character") & nchar(zip) == 5 & !grepl("\\D", zip)){
url <- paste0(
"street=", utils::URLencode(street),
"&city=", utils::URLencode(city),
"&state=", state,
"&zip=", zip
)} else {
message("'zip' (", paste0(zip), ") was not a 5-character-long string composed of :digits:. Using only street, city, state.")
url <- paste0(
"street=", utils::URLencode(street),
"&city=", utils::URLencode(city),
"&state=", state
)
}
}
call_end <- "&benchmark=Public_AR_Census2020&vintage=Census2020_Census2020&layers=10&format=json"
url_full <- paste0(call_start, url, call_end)
# Check response
r <- httr::GET(url_full)
httr::stop_for_status(r)
response <- httr::content(r)
if (length(response$result$addressMatches) == 0) {
message(paste0("Address (",
street, " ", city, " ", state,
") returned no address matches. An NA was returned."))
return(NA_character_)
} else {
if (length(response$result$addressMatches) > 1) {
message(paste0("Address (",
street, " ", city, " ", state,
") returned more than one address match. The first match was returned."))
}
return(response$result$addressMatches[[1]]$geographies$`Census Blocks`[[1]]$GEOID)
}
}
#' Call geolocator for one address with lat/lon, adds option to set benchmark and vintage if not provided it will default to the most recent.
#'
#' @param lat A numeric value
#' @param lon A numeric value
#' @param benchmark time period when a snapshot of address ranges was taken
#' @param vintage census or survey that the address range relates to
#'
#' @return A character string representing the Census block of the supplied
#' lat/lon.
#'
#' @importFrom utils URLencode
#' @importFrom httr GET stop_for_status
#'
#' @author Josie Kressner, \email{josie@@transportfoundry.com}
#' @author Mark Richards, \email{Mark.Richards.002@@gmail.com}
#' @export
#'
call_geolocator_latlon <- function(lat, lon, benchmark, vintage) {
if(missing(benchmark)) {
benchmark<-"Public_AR_Current"
} else {
benchmark<-benchmark
}
if(missing(vintage)) {
vintage<-"Current_Current"
} else {
vintage<-vintage
}
# Build url
call_start <- "https://geocoding.geo.census.gov/geocoder/geographies/coordinates?"
url <- paste0("x=", lon,"&y=", lat)
benchmark0 <- paste0("&benchmark=", benchmark)
vintage0 <- paste0("&vintage=", vintage, "&format=json")
url_full <- paste0(call_start, url, benchmark0, vintage0)
#print(url_full)
# Check response
r <- httr::GET(url_full)
httr::stop_for_status(r)
response <- httr::content(r)
if (length(response$result$geographies$`2020 Census Blocks`[[1]]$GEOID) == 0) {
message(paste0("Lat/lon (", lat, ", ", lon,
") returned no geocodes. An NA was returned."))
return(NA_character_)
} else {
#regex search for block group geography in response
response_block<-grep(response[["result"]][["geographies"]], pattern = ".Block.")
#check If a block group result is found or return NA
#If block group response is found check GEOID length and return either NA for missing data or the value
if(length(response_block) == 0){
return(NA_character_)
} else {
if (length(response[["result"]][["geographies"]][[response_block]][[1]]$GEOID) == 0) {
message(paste0("Lat/lon (", lat, ", ", lon,
") returned no geocodes. An NA was returned."))
return(NA_character_)
} else {
if (length(response[["result"]][["geographies"]][[response_block]][[1]]$GEOID) > 1) {
message(paste0("Lat/lon (", lat, ", ", lon,
") returned more than geocode. The first match was returned."))
}
return(response[["result"]][["geographies"]][[response_block]][[1]]$GEOID)
}
}
}
}
================================================
FILE: R/helpers.R
================================================
#' Set the cache directory to store shapefiles with tigris
#'
#' @description By default, tigris uses the rappdirs package to determine a suitable location to store shapefiles
#' on the user's computer. However, it is possible that the user would want to store shapefiles in a custom
#' location. This function allows users to set the cache directory, and stores the result in the user's
#' .Renviron so that tigris will remember the location.
#'
#' Windows users: please note that you'll need to use double-backslashes or forward slashes
#' when specifying your cache directory's path in R.
#'
#' @param path The full path to the desired cache directory
#' @export
#' @examples \dontrun{
#' # Set the cache directory
#' tigris_cache_dir('PATH TO MY NEW CACHE DIRECTORY')
#'
#' # Check to see if it has been set correctly
#' Sys.getenv('TIGRIS_CACHE_DIR')
#' }
tigris_cache_dir <- function(path) {
home <- Sys.getenv("HOME")
renv <- file.path(home, ".Renviron")
if (!file.exists(renv)) {
file.create(renv)
}
check <- readLines(renv)
if (isTRUE(any(grepl("TIGRIS_CACHE_DIR", check)))) {
oldenv <- read.table(renv, stringsAsFactors = FALSE)
newenv <- oldenv[!grepl("TIGRIS_CACHE_DIR", oldenv$V1), ]
write.table(
newenv,
renv,
quote = FALSE,
sep = "\n",
col.names = FALSE,
row.names = FALSE
)
}
var <- paste0("TIGRIS_CACHE_DIR=", "'", path, "'")
write(var, renv, sep = "\n", append = TRUE)
message(sprintf(
"Your new tigris cache directory is %s. \nTo use now, restart R or run `readRenviron('~/.Renviron')`",
path
))
}
#' Helper function to download Census data
#'
#' @param url URL for zipped shapefile in TIGER database (constructed in calling function).
#' @param refresh Whether to re-download shapefiles if cached. Defaults to value of the global
#' option "tigris_refresh" if that option is, and FALSE if not. This will override the behavior
#' set in "tigris_refresh" option if a value (TRUE or FALSE) is provided.
#' @param tigris_type Added as an attribute to return object (used internally).
#' @param class Class of return object. Must be one of "sf" (the default) or "sp".
#' @param progress_bar If set to FALSE, do not display download progress bar
#' (helpful for R Markdown documents). Defaults to TRUE.
#' @param keep_zipped_shapefile If set to TRUE, do not delete zipped shapefile
#' (stored in temporary directory or TIGRIS_CACHE_DIR depending on the configuration of
#' global option "tigris_use_cache"). Defaults to FALSE.
#' @param filter_by Geometry used to filter the output returned by the function. Can be an sf object, an object of class `bbox`, or a length-4 vector of format `c(xmin, ymin, xmax, ymax)` that can be converted to a bbox. Geometries that intersect the input to `filter_by` will be returned.
#' @param protocol Character string specifying the protocol to use for downloading files. Options are "ftp" or "http" (default). If "ftp", the URL will be modified to use FTP instead of HTTPS.
#' @param timeout Integer specifying the timeout in seconds for download operations. Defaults to 300 (5 minutes) to handle large files.
#'
#' @return sf or sp data frame
#'
load_tiger <- function(
url,
refresh = getOption("tigris_refresh", FALSE),
tigris_type = NULL,
class = getOption("tigris_class", "sf"),
progress_bar = TRUE,
keep_zipped_shapefile = FALSE,
filter_by = NULL,
protocol = getOption("tigris_protocol", "http"),
timeout = 1800
) {
use_cache <- getOption("tigris_use_cache", FALSE)
# Process filter_by
# TODO: Expose geos_method argument used by sf::st_make_valid
wkt_filter <- input_to_wkt(filter_by)
# Store original URL before protocol modification
original_url <- url
# Modify URL for FTP if needed
if (protocol == "ftp" && grepl("^https://www2", url)) {
url <- gsub("^https://www2", "ftp://ftp2", url)
}
tiger_file <- basename(url)
obj <- NULL
if (use_cache) {
if (Sys.getenv("TIGRIS_CACHE_DIR") != "") {
cache_dir <- Sys.getenv("TIGRIS_CACHE_DIR")
cache_dir <- path.expand(cache_dir)
} else {
cache_dir <- user_cache_dir("tigris")
}
if (!file.exists(cache_dir)) {
dir.create(cache_dir, recursive = TRUE)
}
if (file.exists(cache_dir)) {
shape <- gsub(".zip", "", tiger_file)
shape <- gsub("_shp", "", shape) # for historic tracts
file_loc <- file.path(cache_dir, tiger_file)
shp_loc <- file.path(cache_dir, sprintf("%s.shp", shape))
if (refresh | !file.exists(shp_loc)) {
if (grepl("^ftp://", url)) {
# Use download.file for FTP URLs with timeout
options(timeout = timeout)
try(
download.file(
url,
destfile = file_loc,
quiet = !progress_bar,
mode = "wb"
),
silent = TRUE
)
options(timeout = 60) # Reset to R default
} else {
# Use httr::GET for HTTP URLs
if (progress_bar) {
try(
GET(
url,
write_disk(file_loc, overwrite = refresh),
progress(type = "down"),
timeout(timeout)
),
silent = TRUE
)
} else {
try(
GET(
url,
write_disk(file_loc, overwrite = refresh),
timeout(timeout)
),
silent = TRUE
)
}
}
}
if (refresh | !file.exists(shp_loc)) {
unzip_tiger <- function() {
unzip(file_loc, exdir = cache_dir, overwrite = TRUE)
}
remove_zip_tiger <- function() {
if (file.exists(file_loc) && file.exists(shp_loc)) {
invisible(file.remove(file_loc))
}
}
# Logic for handling download errors and re-downloading
t <- tryCatch(unzip_tiger(), warning = function(w) w)
if ("warning" %in% class(t)) {
i <- 1
while (i < 4) {
message(sprintf(
"Previous download failed. Re-download attempt %s of 3...",
as.character(i)
))
if (grepl("^ftp://", url)) {
# Use download.file for FTP URLs with timeout
options(timeout = timeout)
try(
download.file(
url,
destfile = file_loc,
quiet = !progress_bar,
mode = "wb"
),
silent = TRUE
)
options(timeout = 60) # Reset to R default
} else {
# Use httr::GET for HTTP URLs
if (progress_bar) {
try(
GET(
url,
write_disk(file_loc, overwrite = TRUE),
progress(type = "down"),
timeout(timeout)
),
silent = TRUE
)
} else {
try(
GET(
url,
write_disk(file_loc, overwrite = TRUE),
timeout(timeout)
),
silent = TRUE
)
}
}
t <- tryCatch(unzip_tiger(), warning = function(w) w)
if ("warning" %in% class(t)) {
i <- i + 1
# If using HTTP protocol and about to make final retry, try FTP as fallback
if (i == 3 && protocol == "http") {
message("HTTP download failed, trying FTP as fallback...")
ftp_url <- gsub("^https://www2", "ftp://ftp2", original_url)
# Try FTP download
options(timeout = timeout)
try(
download.file(
ftp_url,
destfile = file_loc,
quiet = !progress_bar,
mode = "wb"
),
silent = TRUE
)
options(timeout = 60) # Reset to R default
# Check if FTP download succeeded
t <- tryCatch(unzip_tiger(), warning = function(w) w)
if (!("warning" %in% class(t))) {
break # FTP worked, exit the retry loop
}
}
} else {
break
}
}
if (i == 4) {
stop(
"Download failed with both HTTP and FTP; check your internet connection or the status of the Census Bureau website
at https://www2.census.gov/geo/tiger/ or ftp://ftp2.census.gov/geo/tiger/.",
call. = FALSE
)
}
} else {
unzip_tiger()
if (!keep_zipped_shapefile) {
remove_zip_tiger()
}
}
}
obj <- st_read(
dsn = cache_dir,
layer = shape,
quiet = TRUE,
stringsAsFactors = FALSE,
wkt_filter = wkt_filter
)
if (is.na(st_crs(obj)$proj4string)) {
st_crs(obj) <- "+proj=longlat +datum=NAD83 +no_defs"
}
}
} else {
tmp <- tempdir()
file_loc <- file.path(tmp, tiger_file)
# Try initial download with specified protocol
if (grepl("^ftp://", url)) {
# Use download.file for FTP URLs with timeout
options(timeout = timeout)
try(
download.file(
url,
destfile = file_loc,
quiet = !progress_bar,
mode = "wb"
),
silent = TRUE
)
options(timeout = 60) # Reset to R default
} else {
# Use httr::GET for HTTP URLs
if (progress_bar) {
try(
GET(
url,
write_disk(file_loc),
progress(type = "down"),
timeout(timeout)
),
silent = TRUE
)
} else {
try(
GET(url, write_disk(file_loc), timeout(timeout)),
silent = TRUE
)
}
}
# Try to unzip the file
unzip_result <- tryCatch(
{
unzip(file_loc, exdir = tmp)
TRUE # Success
},
warning = function(w) FALSE, # Failed
error = function(e) FALSE # Failed
)
# If HTTP download failed, try FTP as fallback
if (!unzip_result && protocol == "http") {
message("HTTP download failed, trying FTP as fallback...")
ftp_url <- gsub("^https://www2", "ftp://ftp2", original_url)
# Try FTP download
options(timeout = timeout)
try(
download.file(
ftp_url,
destfile = file_loc,
quiet = !progress_bar,
mode = "wb"
),
silent = TRUE
)
options(timeout = 60) # Reset to R default
# Try to unzip again
unzip_result <- tryCatch(
{
unzip(file_loc, exdir = tmp)
TRUE # Success
},
warning = function(w) FALSE, # Failed
error = function(e) FALSE # Failed
)
if (!unzip_result) {
stop(
"Download failed with both HTTP and FTP; check your internet connection or the status of the Census Bureau website
at https://www2.census.gov/geo/tiger/ or ftp://ftp2.census.gov/geo/tiger/.",
call. = FALSE
)
}
} else if (!unzip_result) {
stop(
"Download failed; check your internet connection or the status of the Census Bureau website
at https://www2.census.gov/geo/tiger/ or ftp://ftp2.census.gov/geo/tiger/.",
call. = FALSE
)
}
shape <- gsub(".zip", "", tiger_file)
shape <- gsub("_shp", "", shape) # for historic tracts
obj <- st_read(
dsn = tmp,
layer = shape,
quiet = TRUE,
stringsAsFactors = FALSE,
wkt_filter = wkt_filter
)
if (is.na(st_crs(obj)$proj4string)) {
st_crs(obj) <- "+proj=longlat +datum=NAD83 +no_defs"
}
}
attr(obj, "tigris") <- "tigris"
# this will help identify the object "sub type"
if (!is.null(tigris_type)) attr(obj, "tigris") <- tigris_type
# Take care of COUNTYFP, STATEFP issues for historic data
if ("COUNTYFP00" %in% names(obj)) {
obj$COUNTYFP <- obj$COUNTYFP00
obj$STATEFP <- obj$STATEFP00
}
if ("COUNTYFP10" %in% names(obj)) {
obj$COUNTYFP <- obj$COUNTYFP10
obj$STATEFP <- obj$STATEFP10
}
if ("COUNTY" %in% names(obj)) {
obj$COUNTYFP <- obj$COUNTY
obj$STATEFP <- obj$STATE
}
if ("CO" %in% names(obj)) {
obj$COUNTYFP <- obj$CO
obj$STATEFP <- obj$ST
}
if (class == "sp") {
warning(
stringr::str_wrap(
"Spatial* (sp) classes are no longer formally supported in tigris as of version 2.0. We strongly recommend updating your workflow to use sf objects (the default in tigris) instead.",
50
),
call. = FALSE
)
return(sf::as_Spatial(obj))
} else {
return(obj)
}
}
#' Easily merge a data frame to a spatial data frame
#'
#' This function should be considered deprecated. Please update your workflow to use sf objects and dplyr's \code{*_join()} family of functions instead.
#'
#' @param spatial_data A spatial data frame to which you want to merge data.
#' @param data_frame A regular data frame that you want to merge to your spatial data.
#' @param by_sp The column name you'll use for the merge from your spatial data frame.
#' @param by_df The column name you'll use for the merge from your regular data frame.
#' @param by (optional) If a named argument is supplied to the by parameter, geo_join will assume that the join columns in the spatial data and data frame share the same name.
#' @param how The type of join you'd like to perform. The default, 'left', keeps all rows in the spatial data frame, and returns NA for unmatched rows. The alternative, 'inner', retains only those rows in the spatial data frame that match rows from the target data frame.
#' @return a joined spatial/data frame object
#' @export
#' @examples \dontrun{
#'
#' library(rnaturalearth)
#' library(WDI)
#' library(tigris)
#'
#' dat <- WDI(country = "all", indicator = "SP.DYN.LE00.IN", start = 2012, end = 2012)
#'
#' dat$SP.DYN.LE00.IN <- round(dat$SP.DYN.LE00.IN, 1)
#'
#' countries <- ne_countries()
#'
#' countries2 <- geo_join(countries, dat, 'iso_a2', 'iso2c')
#'
#' nrow(countries2)
#'
#' ## [1] 177
#'
#' countries3 <- geo_join(countries, dat, 'iso_a2', 'iso2c', how = 'inner')
#'
#' nrow(countries3)
#'
#' ## [1] 169
#'
#' }
geo_join <- function(
spatial_data,
data_frame,
by_sp,
by_df,
by = NULL,
how = 'left'
) {
.Deprecated(
"dplyr::left_join()",
package = "tigris",
msg = "We recommend using the dplyr::*_join() family of functions instead."
)
if (!is.null(by)) {
by_sp <- by
by_df <- by
}
# For sp objects
if (
class(spatial_data)[1] %in%
c(
"SpatialGridDataFrame",
"SpatialLinesDataFrame",
"SpatialPixelsDataFrame",
"SpatialPointsDataFrame",
"SpatialPolygonsDataFrame"
)
) {
spatial_data@data <- data.frame(
spatial_data@data,
data_frame[match(spatial_data@data[[by_sp]], data_frame[[by_df]]), ]
)
if (how == 'inner') {
matches <- match(spatial_data@data[[by_sp]], data_frame[[by_df]])
spatial_data <- spatial_data[!is.na(matches), ]
return(spatial_data)
} else if (how == 'left') {
return(spatial_data)
} else {
stop(
"The available options for `how` are 'left' and 'inner'.",
call. = FALSE
)
}
# For sf objects
} else if ("sf" %in% class(spatial_data)) {
join_vars <- c(by_df)
names(join_vars) <- by_sp
if (how == "inner") {
joined <- spatial_data %>%
inner_join(data_frame, by = join_vars) %>%
st_as_sf()
attr(joined, "tigris") <- tigris_type(spatial_data)
return(joined)
} else if (how == "left") {
# Account for potential duplicate rows in data frame
df_unique <- data_frame %>%
group_by_(by_df) %>%
mutate(rank = row_number()) %>%
filter(rank == 1)
joined <- spatial_data %>%
left_join(df_unique, by = join_vars) %>%
st_as_sf()
if (!is.na(st_crs(spatial_data)$epsg)) {
crs <- st_crs(spatial_data)$epsg
} else {
crs <- st_crs(spatial_data)$proj4string
}
st_crs(joined) <- crs # re-assign the CRS
attr(joined, "tigris") <- tigris_type(spatial_data)
return(joined)
} else {
stop(
"The available options for `how` are 'left' and 'inner'.",
call. = FALSE
)
}
}
}
#' Look up state and county codes
#'
#' Function to look up the FIPS codes for states and optionally counties you'd l
#' ike to load data for. As the package functions require the codes to return
#' the data correctly, this function makes it easy to find the codes that you need.
#'
#' @param state String representing the state you'd like to look up.
#' Accepts state names (spelled correctly), e.g. "Texas", or
#' postal codes, e.g. "TX". Can be lower-case.
#' @param county The name of the county you'll like to search for. T
#' he state that the county is located in must be supplied for this to
#' work, as there are multiple counties with the same names across states.
#' Can be lower-case.
#' @return character string with an explanation of state/county FIPS codes
#' @export
#' @examples \dontrun{
#' lookup_code("me")
#' ## [1] "The code for Maine is '23'."
#'
#' lookup_code("Maine")
#' ## [1] "The code for Maine is '23'."
#'
#' lookup_code("23")
#' ## [1] "The code for Maine is '23'."
#'
#' lookup_code(23)
#' ## [1] "The code for Maine is '23'."
#'
#' lookup_code("me", "york")
#' ## [1] "The code for Maine is '23' and the code for York County is '031'."
#'
#' lookup_code("Maine", "York County")
#' ## [1] "The code for Maine is '23' and the code for York County is '031'."
#' }
lookup_code <- function(state, county = NULL) {
state <- validate_state(state, .msg = FALSE)
if (is.null(state)) stop("Invalid state", call. = FALSE)
if (!is.null(county)) {
vals <- fips_codes[
fips_codes$state_code == state &
grepl(
sprintf("^%s", county),
fips_codes$county,
ignore.case = TRUE
),
]
return(paste0(
"The code for ",
vals$state_name,
" is '",
vals$state_code,
"'",
" and the code for ",
vals$county,
" is '",
vals$county_code,
"'."
))
} else {
vals <- head(fips_codes[fips_codes$state_code == state, ], 1)
return(paste0(
"The code for ",
vals$state_name,
" is '",
vals$state_code,
"'."
))
}
}
#' Returns \code{TRUE} if \code{obj} has a \code{tigris} attribute
#'
#' It's unlikely that said object was not created by this package
#'
#' @param obj R object to test
#' @return \code{TRUE} if \code{obj} was made by this package
#' @export
is_tigris <- function(obj) {
!is.null(attr(obj, "tigris"))
}
#' Get the type of \code{tigris} object \code{obj} is
#'
#' @param obj R object to test
#' @return character vector containing the \code{tigris} type of \code{obj}
#' or \code{NA} if \code{obj} is not a code \code{tigris} object
#' @export
tigris_type <- function(obj) {
if (is_tigris(obj)) return(attr(obj, "tigris"))
return(NA)
}
#' Return a data frame of county names & FIPS codes for a given state
#'
#' @param state String representing the state you'd like to look up.
#' Accepts state names (spelled correctly), e.g. "Texas", or
#' postal codes, e.g. "TX". Can be lower-case.
#' @return data frame of county name and FIPS code or NULL if invalid state
#' @export
list_counties <- function(state) {
state <- validate_state(state, .msg = FALSE)
if (is.null(state)) stop("Invalid state", call. = FALSE)
vals <- fips_codes[
fips_codes$state_code == state,
c("county", "county_code")
]
vals$county <- gsub("\ County$", "", vals$county)
rownames(vals) <- NULL
return(vals)
}
#' Row-bind \code{tigris} Spatial objects
#'
#' If multiple school district types are rbound, coerces to "sdall" and does it
#'
#' @param ... individual (optionally names) \code{tigris} Spatial objects or a list of them
#' @return one combined Spatial object
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' me_ctys <- list_counties("me")
#' aw <- lapply(me_ctys$county_code[1:3], function(x) {
#' area_water("Maine", x)
#' }) %>%
#' rbind_tigris()
#' }
rbind_tigris <- function(...) {
elements <- list(...)
if (
(length(elements) == 1) &
inherits(elements, "list")
) {
elements <- unlist(elements, recursive = FALSE) # Necessary given structure of sf objects
}
obj_classes <- unique(sapply(elements, class))
obj_attrs <- sapply(elements, attr, "tigris")
obj_attrs_u <- unique(obj_attrs)
if (
any(
c(
"SpatialGridDataFrame",
"SpatialLinesDataFrame",
"SpatialPixelsDataFrame",
"SpatialPointsDataFrame",
"SpatialPolygonsDataFrame"
) %in%
obj_classes
) &
"sf" %in% obj_classes
) {
stop("Cannot combine sp and sf objects", call. = FALSE)
}
#handling for attempts to rbind disparate school districts
if (all(obj_attrs %in% c("unsd", "elsd", "scsd"))) {
# 3 school district types
warning(
"Multiple school district tigris types. Coercing to \'sdall\'.",
call. = FALSE
)
elements <- lapply(seq_along(elements), function(x) {
names(elements[[x]])[2] <- "SDLEA" # Used in some spots elsewhere in TIGER
attr(elements[[x]], "tigris") <- "sdall" # New type
elements[[x]]
})
obj_attrs <- sapply(elements, attr, "tigris")
obj_attrs_u <- unique(obj_attrs)
}
# all same type
# all valid Spatial* type
# none are from outside tigris
# all same tigris "type"
if (
obj_classes[1] %in%
c(
"SpatialGridDataFrame",
"SpatialLinesDataFrame",
"SpatialPixelsDataFrame",
"SpatialPointsDataFrame",
"SpatialPolygonsDataFrame"
)
) {
stop(
"Spatial* classes are no longer supported in tigris as of version 2.0. You will need to install an earlier version of tigris with `remotes::install_version()`."
)
} else if ("sf" %in% obj_classes) {
crs <- unique(sapply(elements, function(x) {
return(st_crs(x)$epsg)
}))
if (length(crs) > 1) {
stop("All objects must share a single coordinate reference system.")
}
if (
!any(sapply(obj_attrs, is.null)) &
length(obj_attrs_u) == 1
) {
geometries <- unlist(lapply(elements, function(x) {
geoms <- st_geometry_type(x)
unique(geoms)
}))
# Cast polygon to multipolygon to allow for rbind-ing
# This will need to be checked for linear objects as well
if ("POLYGON" %in% geometries & "MULTIPOLYGON" %in% geometries) {
elements <- lapply(elements, function(x) {
st_cast(x, "MULTIPOLYGON")
})
}
if (
"LINESTRING" %in% geometries & "MULTILINESTRING" %in% geometries
) {
elements <- lapply(elements, function(x) {
st_cast(x, "MULTILINESTRING")
})
}
tmp <- Reduce(rbind, elements) # bind_rows not working atm
# Re-assign the original CRS if missing
if (is.na(st_crs(tmp)$proj4string)) {
st_crs(tmp) <- crs
}
attr(tmp, "tigris") <- obj_attrs_u
return(tmp)
} else {
stop(
"Objects must all be the same type of tigris object.",
call. = FALSE
)
}
}
}
#' Erase water area from an input polygon dataset
#'
#' This function 'erases' water area from an input polygon dataset (typically a Census dataset).
#' 'Erase' is defined in the traditional GIS sense as the removal of areas in an input layer
#' from an erase layer, returning the modified input layer. A common use-case is to improve
#' cartographic representation of locations where US Census polygons include more water area
#' than desired (e.g. New York City, Seattle) or to support contiguity-based spatial analyses that
#' might otherwise incorrectly assume that polygons across bodies of water are neighbors.
#'
#' The function works by identifying US counties that intersect the input polygon layer,
#' then requesting water polygons (using \code{tigris::area_water()}) to be erased from
#' those input polygons. The \code{area_threshold} parameter can be tuned to determine the
#' percentile ranking of bodies of water (by area) to use;
#' the default is a percentile ranking of 0.75, erasing the largest 25 percent of water
#' bodies in the region.
#'
#' Analysts will ideally have transformed the input coordinate reference system (CRS) of their data
#' to a projected CRS to improve performance; see \url{https://walker-data.com/census-r/census-geographic-data-and-applications-in-r.html#coordinate-reference-systems} for more information on
#' how to perform CRS transformations. Analysts should also use this function with caution;
#' the function may generate sliver polygons or irregular geometries in the output layer,
#' especially if the input sf object was not obtained with the tigris package. Also, the operation
#' may be quite slow for large input areas.
#'
#' @param input_sf An input sf object, ideally obtained with the tigris package or through tidycensus.
#' @param area_threshold The percentile rank cutoff of water areas to use in the erase operation, ranked by size. Defaults to 0.75, representing the water areas in the 75th percentile and up (the largest 25 percent of areas). This value may need to be modified by the user to achieve optimal results for a given location.
#' @param year The year to use for the water layer; defaults to 2020 unless the \code{tigris_year} option is otherwise set.
#'
#' @return An output sf object representing the polygons in \code{input_sf} with water areas erased.
#' @export
#'
#' @examples \dontrun{
#'
#' library(tigris)
#' library(sf)
#' options(tigris_use_cache = TRUE)
#'
#' king_tracts <- tracts(state = "WA", county = "King", year = 2020)
#'
#' # CRS: NAD 1983 / Washington North (State Plane)
#' king_erased <- king_tracts %>%
#' st_transform(32148) %>%
#' erase_water(area_threshold = 0.9)
#'
#' plot(king_erased$geometry)
#' }
erase_water <- function(input_sf, area_threshold = 0.75, year = NULL) {
# if (is.null(attr(input_sf, "tigris"))) {
# warning("Your input object does not appear to have been obtained with the tigris package.\nThis is likely to introduce sliver polygons or irregular geometries.\nPlease proceed with caution.")
# }
if (!"sf" %in% class(input_sf)) {
stop("The input dataset is not an sf object.", call. = FALSE)
}
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
}
# Define st_erase function internally
st_erase <- function(x, y) {
suppressWarnings(sf::st_difference(x, sf::st_union(y)))
}
# Grab a dataset of counties quietly
us_counties <- tigris::counties(
cb = TRUE,
resolution = "500k",
progress_bar = FALSE,
year = year
)
# Identify the counties that overlap the input sf object
county_overlay <- us_counties %>%
sf::st_transform(sf::st_crs(input_sf)) %>%
sf::st_filter(input_sf)
# If nothing returned, exit
if (nrow(county_overlay) == 0) {
stop(
"Your dataset does not appear to be in the United States; this function is not appropriate for your data.",
call. = FALSE
)
}
# Get a list of GEOIDs
county_GEOIDs <- county_overlay$GEOID
# Fetch water for those GEOIDs
message("Fetching area water data for your dataset's location...")
my_water <- lapply(county_GEOIDs, function(cty) {
suppressMessages(tigris::area_water(
state = stringr::str_sub(cty, 1, 2),
county = stringr::str_sub(cty, 3, 5),
progress_bar = FALSE,
year = year
))
}) %>%
dplyr::bind_rows() %>%
sf::st_transform(sf::st_crs(input_sf)) %>%
sf::st_filter(input_sf) %>% # New step to only erase intersecting water areas
dplyr::filter(dplyr::percent_rank(AWATER) >= area_threshold)
message(
"Erasing water area...\nIf this is slow, try a larger area threshold value."
)
erased_sf <- suppressMessages(st_erase(input_sf, my_water))
return(erased_sf)
}
#' Documentation Template for Functions that Utilize `load_tiger`
#'
#' @md
#' @details This documentation is inherited by `tigris` functions that wrap `load_tiger`.
#' Include the following in function documentation:
#' `@inheritParams load_tiger_doc_template`
#' `@inheritSection load_tiger_doc_template Additional Arguments`
#'
#' @param ... arguments to be passed to internal function `load_tiger`, which is not exported. See Additional Arguments.
#' @param year the data year; defaults to 2024
#'
#' @section Additional Arguments:
#' Additional arguments that can be passed in `...` are:
#' * `class` Desired class of return object: `"sf"` (the default) or `"sp"`. sp classes should be considered deprecated as of tigris version 2.0, but legacy support is still available.
#' * `progress_bar` If set to `FALSE`, do not display download progress bar (helpful for R Markdown documents). Defaults to `TRUE`.
#' * `keep_zipped_shapefile` If set to `TRUE`, do not delete zipped shapefile (stored in temporary directory or `TIGRIS_CACHE_DIR`
#' depending on the configuration of global option `"tigris_use_cache"`). Defaults to `FALSE`.
#' * `refresh` Whether to re-download cached shapefiles (`TRUE` or `FALSE`) . The default is either `FALSE` or the value of global
#' option `"tigris_refresh"` if it is set. Specifying this argument will override the behavior set in `"tigris_refresh"` global option.
#' * `filter_by` Geometry used to filter the output returned by the function. Can be an sf object, an object of class `bbox`, or a length-4 vector of format `c(xmin, ymin, xmax, ymax)` that can be converted to a bbox. Geometries that intersect the input to `filter_by` will be returned.
#' * `protocol` Character string specifying the protocol to use for downloading files. Options are "ftp" or "http" (default). If "ftp", the URL will be modified to use FTP instead of HTTPS.
#' * `timeout` Integer specifying the timeout in seconds for download operations if protocol is "ftp". Defaults to 1800 (30 minutes) to handle large files.
#' @name load_tiger_doc_template
NULL
================================================
FILE: R/landmarks.R
================================================
#' Download the Military Installation National Shapefile into R
#'
#' Description from the US Census Bureau: "The Census Bureau includes landmarks
#' such as military installations in the MAF/TIGER database for
#' locating special features and to help enumerators during field operations. The Census Bureau adds
#' landmark features to the database on an as-needed basis and does not attempt to ensure that all
#' instances of a particular feature are included. For additional information about area landmarks, please
#' see Section 3.12, Landmarks (Area and Point)."
#'
#' This file does not include the three point landmarks identified as military installation features in the
#' MAF/TIGER database. These point landmarks are included in the point landmark shapefile.
#' Although almost all military installations have assigned 8-character National Standard (GNIS) codes, the
#' Census Bureau has not loaded most of this data into the MAF/TIGER database. The 2020 military
#' shapefiles contain few values in the ANSICODE field.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc_Ch3.pdf}
#' @export
military <- function(year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/MIL/tl_%s_us_mil.zip",
as.character(year),
as.character(year)
)
return(load_tiger(url, tigris_type = "military", ...))
}
#' Download a point or area landmarks shapefile into R
#'
#' Description from the US Census Bureau:
#' "The Census Bureau includes landmarks in the MAF/TIGER database (MTDB) for locating special features
#' and to help enumerators during field operations. Some of the more common landmark types include area
#' landmarks such as airports, cemeteries, parks, and educational facilities and point landmarks such as
#' schools and churches."
#'
#' The Census Bureau adds landmark features to the database on an as-needed basis and makes no
#' attempt to ensure that all instances of a particular feature were included. The absence of a landmark
#' such as a hospital or prison does not mean that the living quarters associated with that landmark were
#' excluded from the 2010 Census enumeration. The landmarks were not used as the basis for building or
#' maintaining the address list used to conduct the 2010 Census.
#'
#' Area landmark and area water features can overlap; for example, a park or other special land-use feature
#' may include a lake or pond. In this case, the polygon covered by the lake or pond belongs to a water
#' feature and a park landmark feature. Other kinds of landmarks can overlap as well. Area landmarks can
#' contain point landmarks, but these features are not linked in the TIGER/Line Shapefiles.
#'
#' Landmarks may be identified by a MAF/TIGER feature class code only and may not have a name. Each
#' landmark has a unique area landmark identifier (AREAID) or point landmark identifier (POINTID) value.
#'
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc_Ch3.pdf}
#'
#' @param state The state for which you'd like to download the landmarks
#' @param type Whether you would like to download point landmarks (\code{"point"}) or area landmarks (\code{"area"}). #' Defaults to \code{"point"}.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @export
landmarks <- function(state, type = "point", year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
state <- validate_state(state)
cyear <- as.character(year)
if (type == "area") {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/AREALM/tl_%s_%s_arealm.zip",
cyear,
cyear,
state
)
return(load_tiger(url, tigris_type = "area_landmark", ...))
} else if (type == "point") {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/POINTLM/tl_%s_%s_pointlm.zip",
cyear,
cyear,
state
)
return(load_tiger(url, tigris_type = "point_landmark", ...))
} else {
stop(
'The argument supplied to type must be either "point" or "area"',
call. = FALSE
)
}
}
================================================
FILE: R/legislative.R
================================================
#' Download a congressional districts shapefile into R
#'
#' Description from the US Census Bureau (see link for source):
#' Congressional districts are the 435 areas from which members are elected to the U.S. House of Representatives. After the apportionment of congressional seats among the states, which is based on decennial census population counts, each state with multiple seats is responsible for establishing congressional districts for the purpose of electing representatives. Each congressional district is to be as equal in population to all other congressional districts in a state as practicable. The boundaries and numbers shown for the congressional districts are those specified in the state laws or court orders establishing the districts within each state.
#'
#' Congressional districts for the 108th through 112th sessions were established by the states based on the result of the 2000 Census. Congressional districts for the 113th through 116th sessions were established by the states based on the result of the 2010 Census. Boundaries are effective until January of odd number years (for example, January 2015, January 2017, etc.), unless a state initiative or court ordered redistricting requires a change. All states established new congressional districts in 2011-2012, with the exception of the seven single member states (Alaska, Delaware, Montana, North Dakota, South Dakota, Vermont, and Wyoming).
#'
#' The current default in tigris reflects boundaries for the 118th Congress, which is available for years 2022 and 2023. Older congressional district boundaries back to 2011 can be obtained by supplying the appropriate year. For the 119th Congress, use `year = 2024`.
#'
#' @param state The two-digit FIPS code (string) of the state you want, or a
#' vector of codes if you want multiple states. Can also be state name
#' or state abbreviation. If \code{NULL} (the default), returns the entire United States.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @param resolution The resolution of the cartographic boundary file (if cb == TRUE).
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family legislative district functions
#' @seealso \url{https://www.census.gov/programs-surveys/geography/guidance/geo-areas/congressional-dist.html}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' cd118 <- congressional_districts(cb = TRUE, resolution = '20m', year = 2022)
#'
#' leaflet(cd118) %>%
#' addTiles() %>%
#' addPolygons()
#' }
congressional_districts <- function(
state = NULL,
cb = FALSE,
resolution = '500k',
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2013 && cb) {
stop(
"`cb = TRUE` for congressional districts is unavailable prior to 2013. Regular TIGER/Line files are available for 2010 through 2010 with `cb = FALSE`",
call. = FALSE
)
}
if (year %in% 2018:2021) {
congress <- "116"
} else if (year %in% 2016:2017) {
congress <- "115"
} else if (year %in% 2014:2015) {
congress <- "114"
} else if (year == 2013) {
congress <- "113"
} else if (year %in% 2011:2012) {
congress <- "112"
} else if (year == 2010) {
congress <- "111"
} else if (year %in% 2022:2023) {
congress <- "118"
} else if (year == 2024) {
congress <- "119"
}
if (year < 2010) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2010.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_cd%s_%s.zip",
cyear,
cyear,
congress,
resolution
)
if (year == 2013) url <- gsub("shp/", "", url)
} else {
# Have to handle 2022 through 2024 differently as national CD file is not available
if (year %in% 2022:2024) {
if (is.null(state)) {
state_codes <- unique(tigris::fips_codes$state_code)
state_codes <- state_codes[state_codes != "74"]
cds <- lapply(state_codes, function(x) {
suppressMessages(tigris::congressional_districts(
state = x,
year = year
))
}) %>%
rbind_tigris()
return(cds)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/CD/tl_%s_%s_cd%s.zip",
cyear,
cyear,
validate_state(state),
congress
)
}
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/CD/tl_%s_us_cd%s.zip",
cyear,
cyear,
congress
)
}
}
cds <- load_tiger(url, tigris_type = "congressional_districts", ...)
state <- unlist(sapply(state, validate_state, USE.NAMES = FALSE))
if (!is.null(state)) {
cds <- cds[cds$STATEFP %in% state, ]
}
return(cds)
}
#' Download a state legislative districts shapefile into R - upper or lower
#'
#' This function allows you to download boundaries for state legislatures into R.
#' Generally, state legislatures are comprised of an "upper" house, which is
#' typically referred to as the Senate, and a "lower" house, which is often (but
#' not exclusively) referred to as the House. The exception is Nebraska, which
#' has a unicameral state legislature.
#'
#' @param state The two-digit FIPS code (string) of the state. Can also be state
#' name or abbreviation (case-insensitive). When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of state legislative districts will be returned.
#' @param house Specify here whether you want boundaries for the \code{upper} or
#' \code{lower} house. Defaults to \code{upper}.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family legislative district functions
#' @seealso \url{https://www.census.gov/programs-surveys/geography/guidance/geo-areas/state-legis-dist.html}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' leg <- state_legislative_districts("Maine", "lower", cb = TRUE)
#'
#' leaflet(leg) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5)
#' }
state_legislative_districts <- function(
state = NULL,
house = "upper",
cb = FALSE,
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message(
"Retrieving state legislative districts for the entire United States"
)
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
if (!house %in% c("upper", "lower"))
stop(
"Must specify 'upper' or 'lower' for 'house' parameter",
call. = FALSE
)
if (house == "lower" & state == "31") {
# Nebraska
type <- "sldu"
} else if (house == "lower") {
type <- "sldl"
} else {
type <- "sldu"
}
cyear <- as.character(year)
if (cb == TRUE) {
if (year == 2010) {
if (type == "sldu") {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_%s_610_u2_500k.zip",
state
)
} else if (type == "sldl") {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_%s_620_l2_500k.zip",
state
)
}
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_%s_500k.zip",
cyear,
cyear,
state,
type
)
if (year == 2013) url <- gsub("shp/", "", url)
} else {
if (year %in% c(2000, 2010)) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/%s/%s/tl_2010_%s_%s%s.zip",
toupper(type),
cyear,
state,
type,
substr(cyear, 3, 4)
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/%s/tl_%s_%s_%s.zip",
cyear,
toupper(type),
cyear,
state,
type
)
}
}
return(load_tiger(url, tigris_type = "state_legislative_districts", ...))
}
#' Download a voting districts shapefile into R
#'
#' Obtain feature geometry for 2020 voting districts, which align with voting districts for the
#' 2020 PL-94171 redistricting data from the US Census Bureau.
#'
#' The US Census Bureau describes \emph{voting districts} as follows:
#' Voting district (VTD) is a generic term adopted by the Bureau of the Census
#' to include the wide variety of small polling areas, such as election districts,
#' precincts, or wards, that State and local governments create for the purpose
#' of administering elections. Some States also use groupings of these entities
#' to define their State and local legislative districts, as well as the districts they
#' define for election of members to the U.S. House of Representatives. In a
#' nationwide cooperative program for the 1980 census, the Census Bureau
#' gave States the opportunity to request use of these election precinct boundaries as the boundaries of #' census enumeration districts (EDs) or, in some areas, census blocks.
#'
#' Support for voting districts in tigris 1.5 and higher is aligned with the 2020 PL redistricting
#' data. The argument \code{cb = FALSE} retrieves voting districts from the TIGER/Line PL
#' shapefiles. A generalized version from the cartographic boundary dataset is available with the
#' argument \code{cb = TRUE}.
#'
#' @param state The state for which you'd like to retrieve data. Can be a state name,
#' state abbreviation, or FIPS code. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of voting districts will be returned.
#' @param county The county for which you are requesting data. Can be a county name or
#' FIPS code. If \code{NULL} (the default), data for the entire state will
#' be returned.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family legislative district functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch14GARM.pdf}
#' @export
#' @examples \dontrun{#'
#' library(tigris)
#'
#' ia <- voting_districts("Iowa")
#'
#' plot(ia$geometry)
#'
#' }
voting_districts <- function(
state = NULL,
county = NULL,
cb = FALSE,
year = 2020,
...
) {
if (year != 2020 && cb == TRUE) {
stop(
"Cartographic boundary voting districts files are only available for 2020.",
call. = FALSE
)
}
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message("Retrieving voting districts for the entire United States")
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2020/shp/cb_2020_%s_vtd_500k.zip",
state
)
vtds <- load_tiger(url, tigris_type = "voting_districts", ...)
if (is.null(county)) {
return(vtds)
} else {
county = validate_county(state, county)
vtds_sub <- vtds[vtds$COUNTYFP20 == county, ]
return(vtds_sub)
}
} else {
if (year == 2012) {
url <- paste0(
"https://www2.census.gov/geo/tiger/TIGER2012/VTD/tl_2012_",
state,
"_vtd10.zip"
)
} else {
if (!is.null(county)) {
county <- validate_county(state, county)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2020PL/LAYER/VTD/2020/tl_2020_%s%s_vtd20.zip",
state,
county
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2020PL/LAYER/VTD/2020/tl_2020_%s_vtd20.zip",
state
)
}
}
return(load_tiger(url, tigris_type = 'voting_districts', ...))
}
}
================================================
FILE: R/metro_areas.R
================================================
#' Download a core-based statistical area shapefile into R
#'
#' Core-based statistical areas include both metropolitan areas and micropolitan areas. The US Census
#' Bureau defines these areas as follows: "A metro area contains a core urban area of 50,000 or more population, and a
#' micro area contains an urban core of at least 10,000 (but less than 50,000) population. Each metro or micro area
#' consists of one or more counties and includes the counties containing the core urban area, as well as any adjacent
#' counties that have a high degree of social and economic integration (as measured by commuting to work) with the urban
#' core." Please see the link provided for more information
#'
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @param resolution The resolution of the cartographic boundary file (if cb == TRUE).
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family metro area functions
#' @seealso \url{https://www.census.gov/programs-surveys/metro-micro.html}
#' @export
core_based_statistical_areas <- function(
cb = FALSE,
resolution = '500k',
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2010) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2010. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
if (cb == TRUE) {
if (year == 2010) {
if (resolution == "5m")
stop(
"Available resolutions are '500k' and '20m'",
call. = FALSE
)
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_310_m1_%s.zip",
resolution
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_cbsa_%s.zip",
cyear,
cyear,
resolution
)
if (year == 2013) url <- gsub("shp/", "", url)
}
} else {
if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/CBSA/2010/tl_2010_us_cbsa10.zip"
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/CBSA/tl_%s_us_cbsa.zip",
cyear,
cyear
)
}
}
return(load_tiger(url, tigris_type = "cbsa", ...))
}
#' Download an urban areas shapefile into R
#'
#' Urban areas include both "urbanized areas," which are densely developed areas with a population of at least 50,000,
#' and "urban clusters," which have a population of greater than 2,500 but less than 50,000. For more information,
#' please see the link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @param criteria If set to "2020" and the year is 2020, will download the new 2020 urban areas criteria. Not available for cartographic boundary shapefiles / other years at the moment.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family metro area functions
#' @seealso \url{https://www.census.gov/programs-surveys/geography/guidance/geo-areas/urban-rural.html}
#' @export
urban_areas <- function(cb = FALSE, year = NULL, criteria = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
cyear <- as.character(year)
if (cb) {
if (!is.null(criteria)) {
stop(
"The `criteria` argument is not supported for cartographic boundary files",
call. = FALSE
)
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_ua10_500k.zip",
cyear,
cyear
)
if (year == 2013) url <- gsub("shp/", "", url)
} else {
if (year >= 2023) {
if (year == 2023) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/UAC/tl_%s_us_uac20.zip",
cyear,
cyear
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/UAC20/tl_%s_us_uac20.zip",
cyear,
cyear
)
}
} else if (!is.null(criteria) && criteria == "2020") {
if (year != 2020) {
stop(
"2020 criteria is only supported when `year` is set to 2020 at the moment.",
call. = FALSE
)
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/UAC/tl_%s_us_uac20.zip",
cyear,
cyear
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/UAC/tl_%s_us_uac10.zip",
cyear,
cyear
)
}
}
return(load_tiger(url, tigris_type = "urban", ...))
}
#' Download a combined statistical areas shapefile into R
#'
#' Combined statistical areas are "two or more adjacent CBSAs that have significant
#' employment interchanges." In turn, CSAs are composed of multiple metropolitan and/or micropolitan areas, and should
#' not be compared with individual core-based statistical areas.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @param resolution The resolution of the cartographic boundary file (if cb == TRUE).
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family metro area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
combined_statistical_areas <- function(
cb = FALSE,
resolution = '500k',
year = NULL,
...
) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year == 2022) {
stop("CBSAs were not defined for 2022; choose a different year.")
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
if (cb == TRUE) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_csa_%s.zip",
cyear,
cyear,
resolution
)
if (year == 2013) url <- gsub("shp/", "", url)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/CSA/tl_%s_us_csa.zip",
cyear,
cyear
)
}
return(load_tiger(url, tigris_type = "csa", ...))
}
#' Download a metropolitan divisions shapefile into R.
#'
#' Metropolitan divisions are subdivisions of metropolitan areas with population of at least 2.5 million. Please note:
#' not all metropolitan areas have metropolitan divisions.
#'
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family metro area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
metro_divisions <- function(year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
cyear <- as.character(year)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/METDIV/tl_%s_us_metdiv.zip",
cyear,
cyear
)
return(load_tiger(url, tigris_type = "metro", ...))
}
#' Download a New England City and Town Area shapefile into R
#'
#' From the US Census Bureau (see link for source): "In New England
#' (Connecticut, Maine, Massachusetts, New Hampshire, Rhode Island,
#' and Vermont), the OMB has defined an alternative county subdivision
#' (generally city and town) based definition of CBSAs
#' known as New England city and town areas (NECTAs). NECTAs are defined using the same criteria as
#' metropolitan and micropolitan statistical areas and are identified as either metropolitan or micropolitan,
#' based, respectively, on the presence of either an urbanized area of 50,000 or more inhabitants or an
#' urban cluster of at least 10,000 and less than 50,000 inhabitants." Combined NECTAs, or CNECTAs, are two or more
#' NECTAs that have significant employment interchange, like Combined Statistical Areas;
#' NECTA divisions are subdivisions of NECTAs.
#'
#' @param type Specify whether to download the New England City and Town Areas file (\code{'necta'}, the default),
#' the combined NECTA file (\code{'combined'}), or the NECTA divisions file (\code{'divisions'}).
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file). Only available when \code{type = 'necta'}.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family metro area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' ne <- new_england(cb = TRUE)
#'
#' plot(ne$geometry)
#'
#' }
new_england <- function(type = 'necta', cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year > 2021) {
stop("New England areas are no longer defined for years after 2021.")
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
cyear <- as.character(year)
if (type == 'necta') {
if (cb == TRUE) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_necta_500k.zip",
cyear,
cyear
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/NECTA/tl_%s_us_necta.zip",
cyear,
cyear
)
}
return(load_tiger(url, tigris_type = "necta", ...))
} else if (type == 'combined') {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/CNECTA/tl_%s_us_cnecta.zip",
cyear,
cyear
)
return(load_tiger(url, tigris_type = "cnecta", ...))
} else if (type == 'divisions') {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/NECTADIV/tl_%s_us_nectadiv.zip",
cyear,
cyear
)
return(load_tiger(url, tigris_type = "nectadiv", ...))
} else {
stop(
"Invalid NECTA type; valid values include 'necta' (the default), 'combined', and 'divisions'.",
call. = FALSE
)
}
}
================================================
FILE: R/national.R
================================================
#' Download a US regions cartographic boundary shapefile into R
#'
#' @param resolution The resolution of the cartographic boundary file.
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#'
#' @family national cartographic boundary functions
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' us_regions <- regions(resolution = '20m')
#'
#' leaflet(us_regions) %>%
#' addTiles() %>%
#' addPolygons()
#' }
#' @export
regions <- function(resolution = '500k', year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_region_%s.zip",
cyear,
cyear,
resolution
)
rgns <- load_tiger(url, tigris_type = "region", ...)
return(rgns)
}
#' Download a US Census divisions cartographic boundary shapefile into R
#'
#' @param resolution The resolution of the cartographic boundary file.
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#'
#' @family national cartographic boundary functions
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' divs <- divisions(resolution = '20m')
#'
#' leaflet(divs) %>%
#' addTiles() %>%
#' addPolygons()
#' }
divisions <- function(resolution = '500k', year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_division_%s.zip",
cyear,
cyear,
resolution
)
div <- load_tiger(url, tigris_type = "division", ...)
return(div)
}
#' Download a US national boundary shapefile into R
#'
#' @param resolution The resolution of the cartographic boundary file.
#' Defaults to '5m'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family national cartographic boundary functions
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' boundary <- nation(resolution = '20m')
#'
#' leaflet(boundary) %>%
#' addTiles() %>%
#' addPolygons()
#' }
nation <- function(resolution = '5m', year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (!(resolution %in% c('5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '5m', and '20m'.",
call. = FALSE
)
}
cyear <- as.character(year)
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_nation_%s.zip",
cyear,
cyear,
resolution
)
nat <- load_tiger(url, tigris_type = "nation", ...)
return(nat)
}
================================================
FILE: R/native.R
================================================
#' Download an American Indian / Alaska Native / Native Hawaiian Areas shapefile into R.
#'
#' Description from the Census Bureau: "This shapefile contain both legal and statistical
#' American Indian, Alaska Native, and Native Hawaiian
#' entities for which the Census Bureau publishes data. The legal entities consist of federally recognized
#' American Indian reservations and off-reservation trust land areas, state-recognized American Indian
#' reservations, and Hawaiian home lands (HHLs)." For more information, please see the link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family native/tribal geometries functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch5GARM.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(ggplot2)
#' library(ggthemes)
#'
#' nat <- native_areas(cb = TRUE)
#'
#' gg <- ggplot()
#' gg <- gg + geom_sf(data = nat, color="black", fill="white", size=0.25)
#' gg <- gg + coord_sf(xlim=c(-179.1506, -129.9795), # alaska
#' ylim=c(51.2097, 71.4410))
#' gg <- gg + theme_map()
#' gg
#' }
native_areas <- function(cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
cyear <- as.character(year)
if (cb == TRUE) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_aiannh_500k.zip",
cyear,
cyear
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/AIANNH/tl_%s_us_aiannh.zip",
cyear,
cyear
)
}
return(load_tiger(url, tigris_type = "native areas", ...))
}
#' Download an American Indian Tribal Subdivision National shapefile into R.
#'
#' Definition from the US Census Bureau: "American Indian Tribal Subdivisions (AITS) are legally defined
#' administrative subdivisions of federally
#' recognized American Indian reservations and/or off-reservation trust lands or Oklahoma tribal statistical
#' areas (OTSAs)." For more information, please see the link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family native/tribal geometries functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch5GARM.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' trib <- tribal_subdivisions_national()
#' leaflet(trib) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5)
#' }
tribal_subdivisions_national <- function(cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_aitsn_500k.zip",
year,
year
)
} else {
if (year < 2015) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/AITS/tl_%s_us_aitsn.zip",
year,
year
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/AITSN/tl_%s_us_aitsn.zip",
year,
year
)
}
}
return(load_tiger(url, tigris_type = "tribal subdivisions", ...))
}
#' Download an Alaska Native Regional Corporation shapefile into R.
#'
#' From the US Census Bureau: "ANRCs are corporations created according to the Alaska Native Claims Settlement Act.
#' They are organized under the laws of the State of
#' Alaska as "Regional Corporations," to conduct both the for-profit and non-profit affairs of Alaska Natives
#' within defined regions of Alaska." For more information, please see the Census technical documentation at the
#' link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family native/tribal geometries functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch5GARM.pdf}
#' @export
alaska_native_regional_corporations <- function(cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
cyear <- as.character(year)
if (cb == TRUE) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_02_anrc_500k.zip",
cyear,
cyear
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/ANRC/tl_%s_02_anrc.zip",
cyear,
cyear
)
}
return(load_tiger(url, tigris_type = "ANRCs", ...))
}
#' Download a Tribal block groups shapefile into R.
#'
#' From the US Census Bureau: "Tribal block groups are subdivisions of a tribal
#' census tract. Tribal block groups were defined by federally
#' recognized tribal government officials in the Census Bureau's
#' Tribal Statistical Areas Program (TSAP) for
#' the 2010 Census. If a tribal government declined to participate in TSAP, the Census Bureau delineated
#' tribal block groups on the American Indian reservation and/or off-reservation trust land (ORTL). Tribal
#' block groups are intended to generally contain between 600 and 3000 persons or between 240 and
#' 1200 housing units. Many American Indian reservations and ORTLs have less than the minimum
#' population thresholds for more than one tribal block group and in those cases one tribal block group was
#' delineated that covers the entire American Indian reservation and/or ORTL. Unlike standard block
#' groups, the cluster of blocks that comprises each tribal block group will not necessarily begin with the
#' same first number of their 4-character census block number,
#' but may contain blocks from several different
#' standard census block groups." For more information, please see the link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family native/tribal geometries functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch5GARM.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' trib <- tribal_block_groups()
#' leaflet(trib) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5)
#' }
tribal_block_groups <- function(cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_tbg_500k.zip"
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TBG/tl_%s_us_tbg.zip",
year,
year
)
}
return(load_tiger(url, tigris_type = "tribal block groups", ...))
}
#' Download a Tribal Census tract shapefile into R.
#'
#' From the US Census Bureau: "Tribal census tracts are relatively small statistical
#' subdivisions of an American Indian reservation and/or
#' off-reservation trust land (ORTL) and were defined by
#' federally recognized tribal government officials in
#' the Census Bureau's Tribal Statistical Areas Program (TSAP) for the 2010 Census. If a tribal government
#' declined to participate in TSAP, the Census Bureau delineated tribal census tracts on the American
#' Indian reservation and/or ORTL. Tribal census tracts are conceptually similar and equivalent to standard
#' census tracts. Unlike standard census tracts, however, tribal census tracts may cross state, county, and
#' standard census tract boundaries." For more information, please view the link provided.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family native/tribal geometries functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch5GARM.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' trib <- tribal_census_tracts()
#' leaflet(trib) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5)
#' }
tribal_census_tracts <- function(cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (cb) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_ttract_500k.zip",
year,
year
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/TTRACT/tl_%s_us_ttract.zip",
year,
year
)
}
return(load_tiger(url, tigris_type = "tribal tracts", ...))
}
================================================
FILE: R/places.R
================================================
#' Download Shapefiles which include both incorporated places (legal entities) and census designated places (statistical entities) into R
#'
#' An incorporated place provides governmental functions for a concentration of people. Incorporated places may extend across county and county subdivision boundaries, but never across state boundaries. An incorporated place usually is a city, town, village, or borough, but can have other legal descriptions. CDPs are the statistical counterparts of incorporated places. CDPs are settled concentrations of population that are identifiable by name but not legally incorporated under the laws of the state in which the CDPs are located. For more information, read appropriate section on "Places" for the correct vintage (year) of your data in the TIGER/Line Shapefiles and TIGER/Line Files Technical Documentation available as of this writing here: \url{https://www.census.gov/programs-surveys/geography/technical-documentation/complete-technical-documentation/tiger-geo-line.html}.
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of places will be returned for years
#' 2019 and later.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' cartographic boundary file. Defaults to FALSE (the most detailed
#' TIGER/Line file).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch9GARM.pdf}
#' @export
places <- function(state = NULL, cb = FALSE, year = NULL, ...) {
if (length(state) > 1) {
p <- lapply(state, function(x) {
places(state = x, cb = cb, year = year, ...)
}) %>%
rbind_tigris()
return(p)
}
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (is.null(state)) {
if (year > 2018 && cb == TRUE) {
state <- "us"
message(
"Retrieving Census-designated places for the entire United States"
)
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
cyear <- as.character(year)
if (cb == TRUE) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_place_500k.zip",
cyear,
cyear,
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/PLACE/tl_%s_%s_place.zip",
cyear,
cyear,
state
)
}
return(load_tiger(url, tigris_type = "place", ...))
}
#' Filter a \code{places} Spatial object for only those places matching the
#' contents of the \code{place} vector.
#'
#' @param places object returned from a call to \code{places}
#' @param place a vector of full place names. The function performs the
#' comparison in a case-insensitive manner.
#' @export
#' @examples \dontrun{
#' places("Maine") %>% filter_place("berwick")
#' }
filter_place <- function(places, place) {
if (is_tigris(places) & tigris_type(places) == "place") {
tmp <- places[tolower(places$NAME) %in% tolower(place), ]
attr(tmp, "tigris") <- "place"
return(tmp)
}
}
#' Find places matching a term in a \code{places} object
#'
#' This is just shorthand for
#' \code{grep(term, list_places(places), value=TRUE, ignore.case=TRUE)}
#'
#' @param places object returned from a call to \code{places}
#' @param term equivalent to the \code{pattern} argument of \code{grep}
#' @export
#' @examples \dontrun{
#' places("Maine") %>% grep_place("south")
#' }
grep_place <- function(places, term) {
if (is_tigris(places) & tigris_type(places) == "place") {
grep(term, list_places(places), value = TRUE, ignore.case = TRUE)
}
}
#' Return a list of all the places in a \code{places} object
#'
#' @param places object returned from a call to \code{places}
#' @param sorted return the list sorted or in the order found in the shapefile?
#' @export
#' @examples \dontrun{
#' places("Maine") %>% list_places()
#' }
list_places <- function(places, sorted = TRUE) {
if (is_tigris(places) & tigris_type(places) == "place") {
if (sorted) return(sort(places$NAME))
return(places$NAME)
}
}
================================================
FILE: R/pumas.R
================================================
#' Download a Public Use Microdata Area (PUMA) shapefile into R
#'
#' Public use microdata areas (PUMAs) are decennial census areas that have been
#' defined for the tabulation and dissemination of Public Use Microdata Sample
#' (PUMS) data, American Community Survey (ACS) data, and ACS period estimates.
#' For the 2010 Census, the State Data Centers (SDCs) in each state, the
#' District of Columbia, and the Commonwealth of Puerto Rico were given the
#' opportunity to delineate PUMAs within their state or
#' statistically equivalent entity. All PUMAs must nest within states and have
#' a minimum population threshold of 100,000 persons. 2010 PUMAs were built on
#' census tracts and cover the entirety of the United States, Puerto Rico,
#' Guam, and the U.S. Virgin Islands. Because they do not meet the minimum
#' population requirement, the Commonwealth of the Northern Mariana Islands
#' and American Samoa do not contain any 2010 PUMAs.
#'
#' @param state The two-digit FIPS code (string) of the state you want. Can also
#' be state name or state abbreviation. When \code{NULL} and combined with
#' \code{cb = TRUE}, a national dataset of PUMAs will be returned when
#' \code{year} is either 2019 or 2020.
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' states file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @export
#' @family general area functions
#' @seealso \url{https://www.census.gov/programs-surveys/geography/guidance/geo-areas/pumas.html}
#' @examples \dontrun{
#' library(tigris)
#'
#' us_states <- unique(fips_codes$state)[1:51]
#'
#' continental_states <- us_states[!us_states %in% c("AK", "HI")]
#' pumas_list <- lapply(continental_states, function(x) {
#' pumas(state = x, cb = TRUE, year = 2017)
#' })
#'
#' us_pumas <- rbind_tigris(pumas_list)
#'
#' plot(us_pumas$geometry)
#' }
pumas <- function(state = NULL, cb = FALSE, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (is.null(state)) {
if (year %in% 2019:2020 && cb) {
state <- "us"
message("Retrieving PUMAs for the entire United States")
} else {
stop(
"A state must be specified for this year/dataset combination.",
call. = FALSE
)
}
} else {
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
}
cyear <- as.character(year)
if (year > 2021) {
suf <- "20"
} else {
suf <- "10"
}
if (cb) {
if (year > 2020) {
stop(
"Cartographic boundary PUMAs are not yet available for years after 2020. Use the argument `year = 2019` for 2010 PUMA boundaries or `year = 2020` for 2020 PUMA boundaries instead to request your data.",
call. = FALSE
)
}
if (year == 2020) {
message(
"The 2020 CB PUMAs use the new 2020 PUMA boundary definitions."
)
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_puma20_500k.zip",
cyear,
cyear,
state
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_%s_puma10_500k.zip",
cyear,
cyear,
state
)
if (year == 2013) url <- gsub("shp/", "", url)
}
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/PUMA/tl_%s_%s_puma%s.zip",
cyear,
cyear,
state,
suf
)
}
pm <- load_tiger(url, tigris_type = "puma", ...)
attr(pm, "tigris") <- "puma"
return(pm)
}
================================================
FILE: R/shift_geometry.R
================================================
#' Shift and rescale Alaska, Hawaii, and Puerto Rico in a US-wide sf object
#'
#' This function will shift and optionally rescale a US dataset for thematic mapping of Alaska,
#' Hawaii, and Puerto Rico with respect to the continental United States. Features in the continental
#' United States will have their CRS transformed to USA Contiguous Albers Equal Area Conic ('ESRI:102003').
#' Alaska, Hawaii, and Puerto Rico features are transformed to appropriate coordinate systems for those areas,
#' then shifted and optionally re-scaled before being assigned the 'ESRI:102003' CRS. Options for users
#' include \code{preserve_area} which allows for preservation of the area of AK/HI/PR relative to the
#' continental US if desired, and two possible arrangements which are specified with \code{position = "below"}
#' or \code{position = "outside"}
#'
#' \code{shift_geometry()}, while designed for use with objects from the tigris package, will work with any US
#' dataset. If aligning datasets from multiple sources, you must take care to ensure that your options
#' specified in \code{preserve_area} and \code{position} are identical across layers. Otherwise your layers
#' will not align correctly.
#'
#' The function is also designed to work exclusively with features in the continental United States,
#' Alaska, Hawaii, and Puerto Rico. If your dataset includes features outside these areas (e.g. other
#' US territories or other countries), you may get unworkable results. It is advisable to filter out
#' those features before using \code{shift_geometry()}.
#'
#' Work on this function is inspired by and adapts some code from Claus Wilke's book \emph{Fundamentals of
#' Data Visualization} (\url{https://clauswilke.com/dataviz/geospatial-data.html}); Bob Rudis's
#' albersusa R package (\url{https://github.com/hrbrmstr/albersusa}); and the ggcart R package
#' (\url{https://uncoast-unconf.github.io/ggcart/}).
#'
#' @param input_sf The input sf dataset
#' @param geoid_column The GEOID column of the dataset that contains a state ID. If used, will speed up
#' processing and avoid spatial overlay to infer locations. Defaults to \code{NULL}.
#' @param preserve_area If TRUE, the areas of Alaska/Hawaii/Puerto Rico relative to the continental US
#' will be preserved. Defaults to FALSE where Alaska is proportionally smaller
#' and Hawaii/Puerto Rico are proportionally larger.
#' @param position One of \code{"below"} (the default) or \code{"outside"}. If \code{"below"}, Alaska, Hawaii,
#' and Puerto Rico will be placed below the continental United States. If \code{"outside"},
#' features will be moved outside the continental US; Alaska will be northwest of Washington,
#' Hawaii southwest of California, and Puerto Rico southeast of Florida.
#'
#' @return The input sf object with transformed geometry
#' @export
#'
#' @examples \dontrun{
#'
#' # Shift and rescale AK/HI/PR for thematic mapping
#' library(tigris)
#' library(tidycensus)
#' library(tidyverse)
#'
#' us_states <- states(cb = TRUE, resolution = "20m") %>%
#' shift_geometry()
#'
#' # Shift but preserve area
#' us_states_eqarea <- states(cb = TRUE, resolution = "20m") %>%
#' shift_geometry(preserve_area = TRUE)
#'
#' # Shift and rescale but position AK/HI/PR outside the continental US rather than below
#' us_states_outside <- states(cb = TRUE, resolution = "20m") %>%
#' shift_geometry(position = "outside")
#'
#' # Shift a dataset obtained outside tigris and make a map
#' income_by_metro <- get_acs(
#' geography = "cbsa",
#' variables = "B01002_001",
#' geometry = TRUE
#' ) %>%
#' shift_geometry()
#'
#
#' ggplot() +
#' geom_sf(data = income_by_metro, aes(fill = estimate), color = NA) +
#' geom_sf(data = us_states, fill = NA, color = "black", size = 0.1) +
#' scale_fill_viridis_c() +
#' theme_void(base_size = 16) +
#' labs(title = "Median age by CBSA, 2015-2019 ACS",
#' fill = "ACS estimate ",
#' caption = "Note: Alaska, Hawaii, and Puerto Rico are shifted and not to scale.") +
#' theme(plot.title = element_text(hjust = 0.5))
#'
#'
#' }
shift_geometry <- function(input_sf,
geoid_column = NULL,
preserve_area = FALSE,
position = c("below", "outside")) {
# sf::sf_use_s2(FALSE)
# Check to see if the input is an sf object, otherwise exit
if (!any(grepl("sf", class(input_sf)))) {
stop("The input dataset must be an sf object.", call = FALSE)
}
position <- match.arg(position)
# Get a set of minimal states which we'll need to use throughout the function
# Do the CRS transformation here to avoid S2 issues with sf 1.0
minimal_states <- tigris::states(cb = TRUE, resolution = "20m", progress_bar = FALSE,
year = 2020) %>%
sf::st_transform('ESRI:102003')
# Make some bboxes to check to see if shifting geometry even makes sense
ak_bbox <- minimal_states %>%
dplyr::filter(GEOID == "02") %>%
sf::st_bbox() %>%
sf::st_as_sfc()
hi_bbox <- minimal_states %>%
dplyr::filter(GEOID == "15") %>%
sf::st_bbox() %>%
sf::st_as_sfc()
pr_bbox <- minimal_states %>%
dplyr::filter(GEOID == "72") %>%
sf::st_bbox() %>%
sf::st_as_sfc()
input_sf <- sf::st_transform(input_sf, sf::st_crs(minimal_states))
ak_check <- suppressMessages(sf::st_intersects(input_sf, ak_bbox, sparse = FALSE)[,1])
hi_check <- suppressMessages(sf::st_intersects(input_sf, hi_bbox, sparse = FALSE)[,1])
pr_check <- suppressMessages(sf::st_intersects(input_sf, pr_bbox, sparse = FALSE)[,1])
if (!any(ak_check) && !any(hi_check) && !any(pr_check)) {
warning("None of your features are in Alaska, Hawaii, or Puerto Rico, so no geometries will be shifted.\nTransforming your object's CRS to 'ESRI:102003'",
call. = FALSE)
transformed_output <- sf::st_transform(input_sf, 'ESRI:102003')
return(transformed_output)
}
# Check to see if there is a GEOID column to identify state information
# If it is a GEOID that works (e.g. counties, tracts), then use it and avoid spatial inferences
if (!is.null(geoid_column)) {
input_sf$state_fips <- stringr::str_sub(input_sf[[geoid_column]], 1, 2)
} else {
# This is where we need to infer the location of the features
# We can do this by checking to see where the input features intersect
# the AK/HI/PR bounding boxes
input_sf <- input_sf %>%
sf::st_transform(sf::st_crs(minimal_states)) %>%
dplyr::mutate(state_fips = dplyr::case_when(
suppressMessages(sf::st_intersects(input_sf, ak_bbox, sparse = FALSE)[,1]) ~ "02",
suppressMessages(sf::st_intersects(input_sf, hi_bbox, sparse = FALSE)[,1]) ~ "15",
suppressMessages(sf::st_intersects(input_sf, pr_bbox, sparse = FALSE)[,1]) ~ "72",
TRUE ~ "00"
))
}
# Alaska/Hawaii/PR centroids are necessary to put any dataset in the correct location
ak_crs <- 3338
hi_crs <- 'ESRI:102007'
pr_crs <- 32161
ak_centroid <- minimal_states %>%
dplyr::filter(GEOID == "02") %>%
sf::st_transform(ak_crs) %>%
sf::st_geometry() %>%
sf::st_centroid()
hi_centroid <- minimal_states %>%
dplyr::filter(GEOID == "15") %>%
sf::st_transform(hi_crs) %>%
sf::st_geometry() %>%
sf::st_centroid()
pr_centroid <- minimal_states %>%
dplyr::filter(GEOID == "72") %>%
sf::st_transform(pr_crs) %>%
sf::st_geometry() %>%
sf::st_centroid()
# Parse the geometries (thanks to Claus Wilke for code samples & inspiration)
place_geometry_wilke <- function(geometry, position,
scale = 1, centroid = sf::st_centroid(geometry)) {
(geometry - centroid) * scale +
sf::st_sfc(st_point(position))
}
cont_us <- dplyr::filter(minimal_states, !GEOID %in% c("02", "15", "72")) %>%
sf::st_transform('ESRI:102003')
us_lower48 <- dplyr::filter(input_sf, !state_fips %in% c("02", "15", "72")) %>%
sf::st_transform('ESRI:102003')
bb <- sf::st_bbox(cont_us)
us_alaska <- dplyr::filter(input_sf, state_fips == "02")
us_hawaii <- dplyr::filter(input_sf, state_fips == "15")
us_puerto_rico <- dplyr::filter(input_sf, state_fips == "72")
# Initialize the list in which shapes will be stored
shapes_list <- list(us_lower48)
# Area not preserved (Alaska smaller, Hawaii bigger)
if (!preserve_area) {
if(any(ak_check)) {
# Rescale and shift Alaska
ak_rescaled <- sf::st_transform(us_alaska, ak_crs)
if (position == "below") {
st_geometry(ak_rescaled) <- place_geometry_wilke(
sf::st_geometry(ak_rescaled),
c(bb$xmin + 0.08*(bb$xmax - bb$xmin),
bb$ymin + 0.07*(bb$ymax - bb$ymin)),
scale = 0.5,
centroid = ak_centroid
)
} else if (position == "outside") {
st_geometry(ak_rescaled) <- place_geometry_wilke(
sf::st_geometry(ak_rescaled),
c(bb$xmin - 0.08*(bb$xmax - bb$xmin),
bb$ymin + 1.2*(bb$ymax - bb$ymin)),
scale = 0.5,
centroid = ak_centroid
)
}
sf::st_crs(ak_rescaled) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(ak_rescaled))
}
if(any(hi_check)) {
# Clip to the Hawaii bbox to take care of the long archipelago
# then rescale and shift Hawaii
hi_rescaled <- suppressWarnings(
us_hawaii %>%
sf::st_intersection(hi_bbox) %>%
sf::st_transform(hi_crs)
)
if (position == "below") {
sf::st_geometry(hi_rescaled) <- place_geometry_wilke(
sf::st_geometry(hi_rescaled),
c(bb$xmin + 0.35*(bb$xmax - bb$xmin),
bb$ymin + 0.*(bb$ymax - bb$ymin)),
scale = 1.5,
centroid = hi_centroid
)
} else if (position == "outside") {
sf::st_geometry(hi_rescaled) <- place_geometry_wilke(
sf::st_geometry(hi_rescaled),
c(bb$xmin - 0.*(bb$xmax - bb$xmin),
bb$ymin + 0.2*(bb$ymax - bb$ymin)),
scale = 1.5,
centroid = hi_centroid
)
}
st_crs(hi_rescaled) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(hi_rescaled))
}
if(any(pr_check)) {
# Rescale and shift Puerto Rico
pr_rescaled <- sf::st_transform(us_puerto_rico, pr_crs)
if (position == "below") {
sf::st_geometry(pr_rescaled) <- place_geometry_wilke(
sf::st_geometry(pr_rescaled),
c(bb$xmin + 0.65*(bb$xmax - bb$xmin),
bb$ymin + 0.*(bb$ymax - bb$ymin)),
scale = 2.5,
centroid = pr_centroid
)
} else if (position == "outside") {
sf::st_geometry(pr_rescaled) <- place_geometry_wilke(
sf::st_geometry(pr_rescaled),
c(bb$xmin + 0.95*(bb$xmax - bb$xmin),
bb$ymin - 0.05*(bb$ymax - bb$ymin)),
scale = 2.5,
centroid = pr_centroid
)
}
st_crs(pr_rescaled) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(pr_rescaled))
}
output_data <- shapes_list %>%
dplyr::bind_rows() %>%
dplyr::select(-state_fips)
return(output_data)
} else {
# Area preserved (Alaska and Hawaii are true to size)
if(any(ak_check)) {
# Shift Alaska but do not rescale
ak_shifted <- sf::st_transform(us_alaska, ak_crs)
if (position == "below") {
st_geometry(ak_shifted) <- place_geometry_wilke(
sf::st_geometry(ak_shifted),
c(bb$xmin + 0.2*(bb$xmax - bb$xmin),
bb$ymin - 0.13*(bb$ymax - bb$ymin)),
scale = 1,
centroid = ak_centroid
)
} else if (position == "outside") {
st_geometry(ak_shifted) <- place_geometry_wilke(
sf::st_geometry(ak_shifted),
c(bb$xmin - 0.25*(bb$xmax - bb$xmin),
bb$ymin + 1.35*(bb$ymax - bb$ymin)),
scale = 1,
centroid = ak_centroid
)
}
sf::st_crs(ak_shifted) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(ak_shifted))
}
# Shift Hawaii but do not rescale
if(any(hi_check)) {
hi_shifted <- suppressWarnings(
us_hawaii %>%
sf::st_intersection(hi_bbox) %>%
sf::st_transform(hi_crs)
)
if (position == "below") {
sf::st_geometry(hi_shifted) <- place_geometry_wilke(
sf::st_geometry(hi_shifted),
c(bb$xmin + 0.6*(bb$xmax - bb$xmin),
bb$ymin - 0.1*(bb$ymax - bb$ymin)),
scale = 1,
centroid = hi_centroid
)
} else if (position == "outside") {
sf::st_geometry(hi_shifted) <- place_geometry_wilke(
sf::st_geometry(hi_shifted),
c(bb$xmin - 0.*(bb$xmax - bb$xmin),
bb$ymin + 0.2*(bb$ymax - bb$ymin)),
scale = 1,
centroid = hi_centroid
)
}
st_crs(hi_shifted) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(hi_shifted))
}
if(any(pr_check)) {
# Shift Puerto Rico but do not rescale
pr_shifted <- sf::st_transform(us_puerto_rico, pr_crs)
if (position == "below") {
sf::st_geometry(pr_shifted) <- place_geometry_wilke(
sf::st_geometry(pr_shifted),
c(bb$xmin + 0.75*(bb$xmax - bb$xmin),
bb$ymin - 0.1*(bb$ymax - bb$ymin)),
scale = 1,
centroid = pr_centroid
)
} else if (position == "outside") {
sf::st_geometry(pr_shifted) <- place_geometry_wilke(
sf::st_geometry(pr_shifted),
c(bb$xmin + 0.95*(bb$xmax - bb$xmin),
bb$ymin - 0.05*(bb$ymax - bb$ymin)),
scale = 1,
centroid = pr_centroid
)
}
st_crs(pr_shifted) <- 'ESRI:102003'
shapes_list <- c(shapes_list, list(pr_shifted))
}
output_data <- shapes_list %>%
dplyr::bind_rows() %>%
dplyr::select(-state_fips)
return(output_data)
}
}
================================================
FILE: R/states.R
================================================
#' Download shapefile for all states into R
#'
#' States and Equivalent Entities are the primary governmental divisions of the
#' United States. In addition to the 50 states, the Census Bureau treats the
#' District of Columbia, Puerto Rico, American Samoa, the Commonwealth of the
#' Northern Mariana Islands, Guam, and the U.S. Virgin Islands as the statistical
#' equivalents of states for the purpose of data presentation.
#'
#' @param cb If cb is set to TRUE, download a generalized (1:500k)
#' states file. Defaults to FALSE (the most detailed TIGER/Line file)
#' @param resolution The resolution of the cartographic boundary file (if cb == TRUE).
#' Defaults to '500k'; options include '5m' (1:5 million) and '20m' (1:20 million).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @export
#' @family general area functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/reference/GARM/Ch4GARM.pdf}
#' @examples \dontrun{
#' library(tigris)
#' library(leaflet)
#'
#' states <- states(cb = TRUE)
#'
#' leaflet(states) %>%
#' addProviderTiles("CartoDB.Positron") %>%
#' addPolygons(fillColor = "white",
#' color = "black",
#' weight = 0.5) %>%
#' setView(-98.5795, 39.8282, zoom=3)
#' }
states <- function(cb = FALSE, resolution = '500k', year = NULL, ...) {
if (!(resolution %in% c('500k', '5m', '20m'))) {
stop(
"Invalid value for resolution. Valid values are '500k', '5m', and '20m'.",
call. = FALSE
)
}
if (is.null(year)) {
year = getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
cyear <- as.character(year)
if (cb == TRUE) {
if (year %in% c(1990, 2000)) {
suf <- substr(as.character(year), 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/PREVGENZ/st/st%sshp/st99_d%s_shp.zip",
suf,
suf
)
} else if (year == 2010) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ2010/gz_2010_us_040_00_%s.zip",
resolution
)
} else {
if (year > 2013) {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_state_%s.zip",
cyear,
cyear,
resolution
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/GENZ%s/shp/cb_%s_us_state_%s.zip",
cyear,
cyear,
resolution
)
}
}
} else {
if (year == 1990)
stop("Please specify `cb = TRUE` to get 1990 data.", call. = FALSE)
if (year %in% c(2000, 2010)) {
suf <- substr(cyear, 3, 4)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER2010/STATE/%s/tl_2010_us_state%s.zip",
cyear,
suf
)
} else {
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/STATE/tl_%s_us_state.zip",
cyear,
cyear
)
}
}
st <- load_tiger(url, tigris_type = "state", ...)
# Dissolve polygons for 1990 and 2000 CB
if (cb && year %in% c(1990, 2000)) {
sclass <- class(st)
if (!any(sclass == "sf")) {
st <- st_as_sf(st)
}
if (year == 1990) {
st <- st %>%
group_by(.data$ST) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
ST99_D90_ = first(.data$ST99_D90_),
ST99_D90_I = first(.data$ST99_D90_I),
NAME = first(.data$NAME)
) %>%
st_cast("MULTIPOLYGON")
} else if (year == 2000) {
st <- st %>%
group_by(.data$STATE) %>%
summarize(
AREA = sum(.data$AREA),
PERIMETER = sum(.data$PERIMETER),
ST99_D00_ = first(.data$ST99_D00_),
ST99_D00_I = first(.data$ST99_D00_I),
NAME = first(.data$NAME),
LSAD = first(.data$LSAD),
REGION = first(.data$REGION),
DIVISION = first(.data$DIVISION),
LSAD_TRANS = first(.data$LSAD_TRANS)
) %>%
st_cast("MULTIPOLYGON")
}
if (any(sclass == "SpatialPolygonsDataFrame")) {
st <- as(st, "Spatial")
}
}
return(st)
}
#' Filter a \code{states} Spatial object for only those states matching the
#' contents of the \code{state} vector.
#'
#' @param states object returned from a call to \code{states}
#' @param state a vector of full state names. The function performs the
#' comparison in a case-insensitive manner.
#' @export
#' @examples \dontrun{
#' states() %>% filter_state("south")
#' }
filter_state <- function(states, state) {
if (is_tigris(states) & tigris_type(states) == "state") {
tmp <- states[tolower(states$NAME) %in% tolower(state), ]
attr(tmp, "tigris") <- "state"
return(tmp)
}
}
#' Find states matching a term in a \code{state} object
#'
#' This is just shorthand for
#' \code{grep(term, list_states(states), value=TRUE, ignore.case=TRUE)}
#'
#' @param states object returned from a call to \code{state}
#' @param term equivalent to the \code{pattern} argument of \code{grep}
#' @export
#' @examples \dontrun{
#' states() %>% grep_state("north")
#' }
grep_state <- function(states, term) {
if (is_tigris(states) & tigris_type(states) == "state") {
grep(term, list_states(states), value = TRUE, ignore.case = TRUE)
}
}
#' Return a list of all the states in a \code{state} object
#'
#' @param states object returned from a call to \code{state}
#' @param sorted return the list sorted or in the order found in the shapefile?
#' @export
#' @examples \dontrun{
#' states() %>% list_states()
#' }
list_states <- function(states, sorted = TRUE) {
if (is_tigris(states) & tigris_type(states) == "state") {
if (sorted) return(sort(states@data$NAME))
return(states@data$NAME)
}
}
================================================
FILE: R/tigris-package.R
================================================
#' Download and use U.S. Census TIGER shapefiles in R
#'
#' tigris is an R package that allows users to directly download and use TIGER/Line and
#' cartographic boundary shapefiles from the US Census Bureau in R. For an overview of the package, visit its repository at \url{https://github.com/walkerke/tigris} or read Chapter 5 of the book \emph{Analyzing US Census Data: Methods, Maps, and Models in R} at \url{https://walker-data.com/census-r/census-geographic-data-and-applications-in-r.html}.
#'
#' Use option \code{tigris_use_cache} to tell \code{tigris} to cache
#' Census shapefile downloads. This is \code{FALSE} by default. e.g.
#' \code{options(tigris_use_cache=TRUE)}
#'
#' Use option \code{tigris_refresh} to force a refresh of cached \code{tigris}
#' Shapefiles. e.g. \code{options(tigris_refresh=TRUE)}
#'
#' Use option \code{tigris_year} to change the year for which you'd like to download data.
#' e.g. \code{options(tigris_year = 2017)}. The default year for the package is 2022.
#'
#' Use option \code{tigris_class} to specify the class of spatial object you'd like returned.
#' The default is \code{"sf"} for simple features objects. If you'd like a legacy object
#' of class \code{Spatial*DataFrame}, use \code{options(tigris_class = "sp")}. Please note
#' that legacy sp objects are no longer formally supported in tigris.
#'
#' Use the \code{protocol} argument in data download functions to specify whether to use FTP or HTTP
#' for downloading files. The default is \code{"ftp"}, which may work better in some environments
#' where HTTPS connections are restricted. For HTTPS downloads, use \code{protocol = "http"}.
#'
#' Use the \code{timeout} parameter to control the timeout for downloading large files when the protocol is FTP. The default is
#' 1800 seconds (30 minutes), which should be sufficient for most files. If you're downloading particularly
#' large files or have a slow connection, you may need to increase this value.
#'
#' @note Several \code{options} and arguments control behavior of various \code{tigris} functions.
#' See \code{Details} for more information.
#' @name tigris-package
#' @aliases tigris
#' @author Kyle Walker (@@kyle_e_walker)
#' @importFrom stringr str_trim str_pad
#' @import utils
#' @import rappdirs
#' @import httr
#' @import uuid
#' @import sf
#' @import dplyr
#' @importFrom cli cli_abort cli_warn cli_inform
#' @import rlang
#' @importFrom methods as
NULL
#' @keywords internal
"_PACKAGE"
#' tigris exported operators
#'
#'
#' @name tigris-exports
NULL
#' Pipe operator
#'
#' @importFrom magrittr %>%
#' @name %>%
#' @export
#' @rdname tigris-exports
NULL
================================================
FILE: R/transportation.R
================================================
#' Download a roads shapefile into R
#'
#' From the Census Bureau: "The content of the all roads shapefile includes
#' primary roads, secondary roads, local neighborhood roads,
#' rural roads, city streets, vehicular trails (4WD), ramps, service drives,
#' walkways, stairways, alleys, and private roads."
#'
#' @param state A character vector of the two-digit FIPS code of the state of the county
#' you'd like to download the roads for. Can also be state name or abbreviation
#' (case-insensitive).
#' @param county A character vector of the three-digit FIPS code of the county you'd like
#' the roads for. Can also be a county name.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family transportation functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @returns
#' an sf object with columns
#' - `LINEARID`: a unique line feature identifier [(source)](https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2019/TGRSHP2019_TechDoc.pdf)
#' - `FULLNAME`: display name [(source)](https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2019/TGRSHP2019_TechDoc.pdf)
#' - `RTTYP`: describes the types of roads used [(source)](https://www.census.gov/library/reference/code-lists/route-type-codes.html). Possible values are:
#' - "C": county
#' - "I": interstate
#' - "M": common name
#' - "O": other
#' - "S": state regonized
#' - "U": U.S.
#' - `MTFCC`: 5-digit geographic code assignment [(see annual assignments)](https://www.census.gov/library/reference/code-lists/mt-feature-class-codes.html)
#' @examples \dontrun{
#' library(tigris)
#' library(ggplot2)
#' library(ggthemes)
#'
#' roads <- roads("Maine", "031")
#'
#' gg <- ggplot()
#' gg <- gg + geom_sf(data = roads,
#' color="black", fill="white", size=0.25)
#' gg <- gg + theme_map()
#' gg
#' }
roads <- function(state, county, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
if (length(county) > 1) {
r <- lapply(county, function(x) {
roads(state = state, county = x, year = year, ...)
}) %>%
rbind_tigris()
return(r)
}
state <- validate_state(state)
county <- validate_county(state, county)
if (is.null(state)) stop("Invalid state", call. = FALSE)
if (is.null(county)) stop("Invalid county", call. = FALSE)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/ROADS/tl_%s_%s%s_roads.zip",
as.character(year),
as.character(year),
state,
county
)
return(load_tiger(url, tigris_type = "road", ...))
}
#' Download a national primary roads shapefile into R
#'
#' From the Census Bureau: "Primary roads are generally divided,
#' limited-access highways within the Federal interstate highway
#' system or under state management. These highways are distinguished by the
#' presence of interchanges
#' and are accessible by ramps and may include some toll highways."
#'
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @inherit roads return
#' @family transportation functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' rds <- primary_roads()
#'
#' plot(rds$geometry)
#'
#' }
primary_roads <- function(year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/PRIMARYROADS/tl_%s_us_primaryroads.zip",
as.character(year),
as.character(year)
)
return(load_tiger(url, tigris_type = "primary_roads", ...))
}
#' Download a primary & secondary roads shapefile into R
#'
#' From the Census Bureau: "Primary roads are generally divided,
#' limited-access highways within the Federal interstate highway
#' system or under state management. These highways are distinguished by the presence of interchanges
#' and are accessible by ramps and may include some toll highways. Secondary roads are main arteries,
#' usually in the U.S. highway, state
#' highway, or county highway system. These roads have one or more lanes of
#' traffic in each direction, may
#' or may not be divided, and usually have at-grade intersections with many other roads and driveways.
#'
#' @param state The two-digit FIPS code of the state of the county you'd like
#' to download the roads for. Can also be state name or abbreviation
#' (case-insensitive).
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @inherit roads return
#' @family transportation functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' rds <- primary_secondary_roads()
#'
#' plot(rds$geometry)
#'
#' }
primary_secondary_roads <- function(state, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
state <- validate_state(state)
if (is.null(state)) stop("Invalid state", call. = FALSE)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/PRISECROADS/tl_%s_%s_prisecroads.zip",
as.character(year),
as.character(year),
state
)
return(load_tiger(url, tigris_type = "prim_sec_roads", ...))
}
#' Download a national rails shapefile into R
#'
#' National dataset for US railroads, including carlines, streetcars,
#' monorails, mass transit, cog rail, incline rail, and trams.
#'
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family transportation functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
#' @examples \dontrun{
#' library(tigris)
#'
#' rls <- rails()
#'
#' plot(rls$geometry)
#'
#' }
rails <- function(year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/RAILS/tl_%s_us_rails.zip",
as.character(year),
as.character(year)
)
return(load_tiger(url, tigris_type = "rails", ...))
}
#' Download an address range features shapefile into R
#'
#' @param state The two-digit FIPS code of the state of the county you'd like
#' to download the roads for. Can also be state name or abbreviation
#' (case-insensitive).
#' @param county The three-digit FIPS code of the county you'd like the roads for.
#' Can also be a county name.
#' @inheritParams load_tiger_doc_template
#' @inheritSection load_tiger_doc_template Additional Arguments
#' @family transportation functions
#' @seealso \url{https://www2.census.gov/geo/pdfs/maps-data/data/tiger/tgrshp2020/TGRSHP2020_TechDoc.pdf}
#' @export
address_ranges <- function(state, county, year = NULL, ...) {
if (is.null(year)) {
year <- getOption("tigris_year", 2024)
message(sprintf("Retrieving data for the year %s", year))
}
if (year < 2011) {
fname <- as.character(match.call())[[1]]
msg <- sprintf(
"%s is not currently available for years prior to 2011. To request this feature,
file an issue at https://github.com/walkerke/tigris.",
fname
)
stop(msg, call. = FALSE)
}
state <- validate_state(state)
county <- validate_county(state, county)
if (is.null(state)) stop("Invalid state", call. = FALSE)
if (is.null(county)) stop("Invalid county", call. = FALSE)
url <- sprintf(
"https://www2.census.gov/geo/tiger/TIGER%s/ADDRFEAT/tl_%s_%s%s_addrfeat.zip",
as.character(year),
as.character(year),
state,
county
)
return(load_tiger(url, tigris_type = "address_range", ...))
}
================================================
FILE: R/utils.R
================================================
#' Check input argument
#' @noRd
check_tigris_arg <- function(
arg,
require_arg = FALSE,
allow_null = TRUE,
multiple = FALSE,
error_arg = caller_arg(arg),
error_call = caller_env()
) {
if (is.null(arg)) {
if (allow_null && !require_arg) {
return(invisible(NULL))
}
cli_abort("{.arg {error_arg}} can't be `NULL`", call = error_call)
}
# Error if length is greater than 1
if (!multiple && length(arg) > 1) {
cli_abort(
"{.arg {error_arg}} must be length 1, not length {length(arg)}",
error_call = error_call
)
}
}
#' Is x only digits?
#' @noRd
is_digits <- function(x) {
grepl("^[[:digit:]]+$", x)
}
#' Is x only alpha characters?
#' @noRd
is_alpha <- function(x) {
grepl("^[[:alpha:]]+", x)
}
#' Pad a short FIPS code
#' @noRd
pad_fips <- function(string, width = 2) {
pad_str(string, width = width, pad = "0")
}
#' Is x a state FIPS?
#' @noRd
is_stfips <- function(x) {
is_digits(x) & (nchar(x) == 2) & (x %in% fips_state_table[["fips"]])
}
#' Is x a state name?
#' @noRd
is_stname <- function(x) {
(nchar(x) > 2) & (tolower(x) %in% fips_state_table[["name"]])
}
#' Is x a state USPS abbreviation?
#' @noRd
is_stusps <- function(x) {
is_alpha(x) & (nchar(x) == 2) & (tolower(x) %in% fips_state_table[["abb"]])
}
#' Match state name values
#' @noRd
match_state_name <- function(
state,
multiple = FALSE,
require_state = FALSE,
error_arg = caller_arg(state),
error_call = caller_env()
) {
state <- tolower(state)
state_fips <- rep_along(state, NA_character_)
is_state_abb <- is_stusps(state)
if (any(is_state_abb)) {
state_abb <- match(state, fips_state_table[["abb"]])
state_abb <- state_abb[!is.na(state_abb)]
state_fips[is_state_abb] <- fips_state_table[state_abb, "fips"]
}
is_state_name <- is_stname(state)
if (any(is_state_name)) {
state_names <- match(state, fips_state_table[["name"]])
state_names <- state_names[!is.na(state_names)]
state_fips[is_state_name] <- fips_state_table[state_names, "fips"]
}
if (!require_state) {
return(state_fips)
}
arg_match(
state_fips,
multiple = multiple,
values = fips_state_table[["fips"]],
error_arg = error_arg,
error_call = error_call
)
}
#' Match state FIPS to valid values
#' @noRd
match_state_fips <- function(
state,
values = NULL,
strict = FALSE,
multiple = FALSE,
require_state = FALSE,
error_arg = "state",
error_call = caller_env()
) {
# forgive 1-digit FIPS codes or county FIPS codes
if (!strict) {
short_state <- nchar(state) < 2
long_state <- nchar(state) > 2
if (any(short_state)) {
state[short_state] <- pad_fips(state[short_state], 2)
}
if (any(long_state)) {
cli_inform(
"Subsetting first two digits from supplied {.arg {error_arg}} to make valid FIPS codes: {state[long_state]}"
)
state[long_state] <- substr(state[long_state], 1, 2)
}
}
values <- values %||% fips_state_table[["fips"]]
valid_state <- state %in% values
if (all(valid_state)) {
return(state)
}
if (!require_state) {
state[!valid_state] <- NA_character_
return(state)
}
arg_match(
state,
multiple = multiple,
values = values,
error_arg = error_arg,
error_call = error_call
)
}
#' Check if state is a FIPS code, full name or abbreviation
#'
#' [validate_state()] checks if an input state values is a FIPS code, full name
#' or abbreviation. If some or all input values are invalid, error if
#' `require_state = TRUE`, return `NULL` if all inputs are invalid, or warn and
#' return valid input values.
#'
#' @param state State name, abbreviation, or FIPS code. Not case sensitive. If a
#' single digits FIPS code or longer county FIPS code is passed, the values
#' are padded with "0" to subset to allow use as a state value.
#' @param allow_null If `TRUE` (default), allow `NULL` input values by invisibly
#' returning `NULL`.
#' @param require_state If `FALSE` (default), warn instead of error on invalid
#' input values.
#' @param multiple If `FALSE` (default), require input to match a single state
#' or county. If `TRUE`, allow multiple values.
#' @param .msg If `TRUE` (default), show informative messages about FIPS code
#' usage. Uses `is_interactive()` by default.
#' @param error_call The execution environment of a currently running function.
#' @returns
#' - `NULL` if input is `NULL` and `allow_null = TRUE` and `require_state = FALSE`
#' - valid state FIPS code if input is even pseudo-valid (i.e. single digit but w/in range)
#' - `NULL` if input is not a valid FIPS code and `require_state = FALSE`
#' - errors if input is not a valid FIPS code and `require_state = TRUE` or if `state` matched multiple values
#' @export
validate_state <- function(
state,
allow_null = TRUE,
require_state = FALSE,
multiple = FALSE,
.msg = is_interactive(),
error_call = caller_env()
) {
check_tigris_arg(
state,
allow_null = allow_null,
require_arg = require_state,
multiple = multiple,
error_call = error_call
)
if (allow_null && is.null(state)) {
return(invisible(NULL))
}
# forgive white space
state <- trimws(state)
state_fips <- rep_along(state, NA_character_)
state_likely_fips <- is_digits(state)
state_likely_name <- is_alpha(state)
# Match state FIPS codes
if (any(state_likely_fips)) {
state_fips[state_likely_fips] <- match_state_fips(
state[state_likely_fips],
multiple = multiple,
require_state = require_state,
error_call = error_call
)
}
# Match state names and abbreviations
if (any(state_likely_name)) {
state_fips[state_likely_name] <- match_state_name(
state[state_likely_name],
multiple = multiple,
require_state = require_state,
error_call = error_call
)
}
state_is_fips <- is_stfips(state_fips)
if (.msg && any(state_is_fips)) {
# Show informative messages about successful state matches
valid_state_fips <- state_fips[state_is_fips]
valid_state_names <- state[state_is_fips]
message_parts <- paste0(
valid_state_fips,
" for ",
valid_state_names,
collapse = ", "
)
cli_inform(c(
"*" = "Using FIPS code{?s} {message_parts}"
))
}
if (all(state_is_fips)) {
return(state_fips)
}
if (!any(state_is_fips) && require_state) {
cli_abort(
"{.arg state} must contain a valid FIPS codes or state name/abbreviations.",
call = error_call
)
}
message <- "{.arg state} contains {cli::no(length(state[!state_is_fips]))} invalid FIPS code{?s} or state name/abbreviations: {.val {state[!state_is_fips]}}"
cli_warn(message, call = error_call)
if (length(state[state_is_fips]) == 0) {
return(NULL)
}
state[state_is_fips]
}
#' Get a vector of county FIPS codes named with county names
#' @noRd
county_values <- function(
state,
...,
require_state = TRUE,
multiple = FALSE,
error_call = caller_env()
) {
# Remove .msg from ... to avoid conflicts
dots <- list(...)
dots[[".msg"]] <- NULL
state <- do.call(validate_state, c(
list(
state = state,
require_state = require_state,
multiple = multiple,
.msg = FALSE,
error_call = error_call
),
dots
))
if (!require_state && is.null(state)) {
return(NULL)
}
state_counties <- tigris::fips_codes[
tigris::fips_codes[["state_code"]] == state,
]
set_names(state_counties[["county_code"]], state_counties[["county"]])
}
#' Match county FIPS values
#' @noRd
match_county_fips <- function(
county,
values = NULL,
state = NULL,
multiple = FALSE,
require_county = FALSE,
strict = FALSE,
error_call = caller_env()
) {
if (is.null(values) && !is.null(state)) {
values <- county_values(state, error_call = error_call)
}
# forgive 1-digit FIPS codes or county FIPS codes
if (!strict) {
short_county <- nchar(county) < 3
if (any(short_county)) {
county[short_county] <- pad_fips(county[short_county], 3)
}
}
valid_county <- county %in% values
if (all(valid_county)) {
return(county)
}
if (!require_county) {
county[!valid_county] <- NA_character_
return(county)
}
arg_match(
county,
values = values,
multiple = multiple,
error_call = error_call
)
}
#' Match county name values
#' @noRd
match_county_name <- function(
county,
values = NULL,
state = NULL,
require_county = FALSE,
multiple = FALSE,
error_call = caller_env()
) {
if (is.null(values) && !is.null(state)) {
values <- county_values(state, error_call = error_call)
}
county_matches <- lapply(
sprintf("^%s", county),
function(p) {
values[grepl(p, names(values), ignore.case = TRUE)]
}
)
missing_matches <- vapply(county_matches, is_empty, logical(1))
uncertain_matches <- vapply(
county_matches,
function(x) {
length(x) > 1
},
logical(1)
)
message <- NULL
if (!any(missing_matches) && !any(uncertain_matches)) {
return(as.character(county_matches))
}
if (any(missing_matches)) {
missing_county <- county[missing_matches]
county_matches[missing_matches] <- NA_character_
message <- c(
message,
"{.arg county} input can't be matched to any valid value: {missing_county}"
)
}
if (any(uncertain_matches)) {
# For ambiguous matches, use the first match and warn about alternatives
for (i in which(uncertain_matches)) {
matches <- county_matches[[i]]
county_matches[[i]] <- matches[1] # Use first match
gitextract_yatmm7b4/ ├── .Rbuildignore ├── .github/ │ ├── .gitignore │ ├── FUNDING.yml │ └── workflows/ │ └── R-CMD-check.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS ├── R/ │ ├── enumeration_units.R │ ├── fips_codes.R │ ├── geocode.R │ ├── helpers.R │ ├── landmarks.R │ ├── legislative.R │ ├── metro_areas.R │ ├── national.R │ ├── native.R │ ├── places.R │ ├── pumas.R │ ├── shift_geometry.R │ ├── states.R │ ├── tigris-package.R │ ├── transportation.R │ ├── utils.R │ ├── water.R │ └── zzz.R ├── README.md ├── data/ │ └── fips_codes.rda ├── data-raw/ │ ├── national_county.txt │ ├── prep-zip-lookup.R │ ├── prep_codes.R │ ├── state.txt │ └── zcta_county_rel_10.txt ├── man/ │ ├── address_ranges.Rd │ ├── alaska_native_regional_corporations.Rd │ ├── append_geoid.Rd │ ├── area_water.Rd │ ├── block_groups.Rd │ ├── blocks.Rd │ ├── call_geolocator.Rd │ ├── call_geolocator_latlon.Rd │ ├── coastline.Rd │ ├── combined_statistical_areas.Rd │ ├── congressional_districts.Rd │ ├── core_based_statistical_areas.Rd │ ├── counties.Rd │ ├── county_subdivisions.Rd │ ├── divisions.Rd │ ├── erase_water.Rd │ ├── filter_place.Rd │ ├── filter_state.Rd │ ├── fips_codes.Rd │ ├── geo_join.Rd │ ├── grep_place.Rd │ ├── grep_state.Rd │ ├── is_tigris.Rd │ ├── landmarks.Rd │ ├── linear_water.Rd │ ├── list_counties.Rd │ ├── list_places.Rd │ ├── list_states.Rd │ ├── load_tiger.Rd │ ├── load_tiger_doc_template.Rd │ ├── lookup_code.Rd │ ├── metro_divisions.Rd │ ├── military.Rd │ ├── nation.Rd │ ├── native_areas.Rd │ ├── new_england.Rd │ ├── places.Rd │ ├── primary_roads.Rd │ ├── primary_secondary_roads.Rd │ ├── pumas.Rd │ ├── rails.Rd │ ├── rbind_tigris.Rd │ ├── regions.Rd │ ├── roads.Rd │ ├── school_districts.Rd │ ├── shift_geometry.Rd │ ├── state_legislative_districts.Rd │ ├── states.Rd │ ├── tigris-exports.Rd │ ├── tigris-package.Rd │ ├── tigris_cache_dir.Rd │ ├── tigris_type.Rd │ ├── tracts.Rd │ ├── tribal_block_groups.Rd │ ├── tribal_census_tracts.Rd │ ├── tribal_subdivisions_national.Rd │ ├── urban_areas.Rd │ ├── validate_county.Rd │ ├── validate_state.Rd │ ├── voting_districts.Rd │ └── zctas.Rd ├── tests/ │ ├── testthat/ │ │ ├── _snaps/ │ │ │ ├── enumeration_units.md │ │ │ └── landmarks.md │ │ ├── test-enumeration_units.R │ │ ├── test-geocode.R │ │ ├── test-landmarks.R │ │ ├── test-legislative.R │ │ ├── test-lookup_helper.R │ │ ├── test-metro_areas.R │ │ ├── test-national.R │ │ ├── test-native.R │ │ ├── test-places.R │ │ ├── test-pumas.R │ │ ├── test-shift_geometry.R │ │ ├── test-states.R │ │ ├── test-transportation.R │ │ ├── test-water.R │ │ └── test_lookup_helper.R │ └── testthat.R └── tigris.Rproj
Condensed preview — 114 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,155K chars).
[
{
"path": ".Rbuildignore",
"chars": 126,
"preview": "^.*\\.Rproj$\n^\\.Rproj\\.user$\n^data-raw$\n^\\.travis\\.yml$\n^tigris\\.Rcheck$\n^tigris.*\\.tar\\.gz$\n^tigris.*\\.tgz$\n^img$\n\n^\\.gi"
},
{
"path": ".github/.gitignore",
"chars": 7,
"preview": "*.html\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 101,
"preview": "# These are supported funding model platforms\n\ngithub: walkerke\ncustom: https://paypal.me/walkerdata\n"
},
{
"path": ".github/workflows/R-CMD-check.yaml",
"chars": 1396,
"preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
},
{
"path": ".gitignore",
"chars": 82,
"preview": ".Rproj.user\n.Rhistory\n.RData\n.Ruserdata\ntigris.Rcheck/\ntigris*.tar.gz\ntigris*.tgz\n"
},
{
"path": "DESCRIPTION",
"chars": 1118,
"preview": "Package: tigris\nType: Package\nTitle: Load Census TIGER/Line Shapefiles\nVersion: 2.2.1.9000\nDate: 2025-07-18\nAuthors@R: c"
},
{
"path": "LICENSE",
"chars": 41,
"preview": "YEAR: 2016\nCOPYRIGHT HOLDER: Kyle Walker\n"
},
{
"path": "NAMESPACE",
"chars": 1691,
"preview": "# Generated by roxygen2: do not edit by hand\n\nexport(\"%>%\")\nexport(address_ranges)\nexport(alaska_native_regional_corpora"
},
{
"path": "NEWS",
"chars": 5418,
"preview": "tigris development\n-------------------------------------------------------\n* Add `{rlang}` and `{cli}` packages to Impor"
},
{
"path": "R/enumeration_units.R",
"chars": 42498,
"preview": "#' Download a US Counties shapefile into R, and optionally subset by state\n#'\n#' Description from the US Census Bureau ("
},
{
"path": "R/fips_codes.R",
"chars": 957,
"preview": "#' Dataset with FIPS codes for US states and counties\n#'\n#' Built-in dataset for use with the \\code{lookup_code} functio"
},
{
"path": "R/geocode.R",
"chars": 6794,
"preview": "#' Retrieve GEOID from the Census Geocoder by address\n#'\n#' Returns GEOID for 2020 geographies.\n#'\n#' @param address A t"
},
{
"path": "R/helpers.R",
"chars": 34788,
"preview": "#' Set the cache directory to store shapefiles with tigris\n#'\n#' @description By default, tigris uses the rappdirs packa"
},
{
"path": "R/landmarks.R",
"chars": 5315,
"preview": "#' Download the Military Installation National Shapefile into R\n#'\n#' Description from the US Census Bureau: \"The Census"
},
{
"path": "R/legislative.R",
"chars": 14788,
"preview": "#' Download a congressional districts shapefile into R\n#'\n#' Description from the US Census Bureau (see link for source)"
},
{
"path": "R/metro_areas.R",
"chars": 13521,
"preview": "#' Download a core-based statistical area shapefile into R\n#'\n#' Core-based statistical areas include both metropolitan "
},
{
"path": "R/national.R",
"chars": 4732,
"preview": "#' Download a US regions cartographic boundary shapefile into R\n#'\n#' @param resolution The resolution of the cartograph"
},
{
"path": "R/native.R",
"chars": 11660,
"preview": "#' Download an American Indian / Alaska Native / Native Hawaiian Areas shapefile into R.\n#'\n#' Description from the Cens"
},
{
"path": "R/places.R",
"chars": 5092,
"preview": "#' Download Shapefiles which include both incorporated places (legal entities) and census designated places (statistical"
},
{
"path": "R/pumas.R",
"chars": 4374,
"preview": "#' Download a Public Use Microdata Area (PUMA) shapefile into R\n#'\n#' Public use microdata areas (PUMAs) are decennial c"
},
{
"path": "R/shift_geometry.R",
"chars": 14102,
"preview": "#' Shift and rescale Alaska, Hawaii, and Puerto Rico in a US-wide sf object\n#'\n#' This function will shift and optionall"
},
{
"path": "R/states.R",
"chars": 6485,
"preview": "#' Download shapefile for all states into R\n#'\n#' States and Equivalent Entities are the primary governmental divisions "
},
{
"path": "R/tigris-package.R",
"chars": 2636,
"preview": "#' Download and use U.S. Census TIGER shapefiles in R\n#'\n#' tigris is an R package that allows users to directly downloa"
},
{
"path": "R/transportation.R",
"chars": 9655,
"preview": "#' Download a roads shapefile into R\n#'\n#' From the Census Bureau: \"The content of the all roads shapefile includes\n#' p"
},
{
"path": "R/utils.R",
"chars": 15662,
"preview": "#' Check input argument\n#' @noRd\ncheck_tigris_arg <- function(\n arg,\n require_arg = FALSE,\n allow_null = TRUE,\n mult"
},
{
"path": "R/water.R",
"chars": 5647,
"preview": "#' Download an area water shapefile into R\n#'\n#' From the US Census Bureau: \"The area hydrography shapefile contains the"
},
{
"path": "R/zzz.R",
"chars": 2395,
"preview": "# via: http://www.epa.gov/envirofw/html/codes/state.html\n#\n# this somewhat duplicates \"state_codes\" but it's primarily i"
},
{
"path": "README.md",
"chars": 4663,
"preview": "# tigris\n\n<img src=tools/readme/tigris_sticker.png width=\"250\">\n\n[\n\nlookup <- read_csv(\"data-raw/zcta_county_rel_10.txt\")\n\nout <- select(lookup, ZCTA5, STATE, COUNTY)\n\n"
},
{
"path": "data-raw/prep_codes.R",
"chars": 2412,
"preview": "library(dplyr)\n\ncounty_codes <- read.csv('data-raw/national_county.txt', header = FALSE, colClasses = \"character\")\n\nstat"
},
{
"path": "data-raw/state.txt",
"chars": 1485,
"preview": "STATE|STUSAB|STATE_NAME|STATENS\n01|AL|Alabama|01779775\n02|AK|Alaska|01785533\n04|AZ|Arizona|01779777\n05|AR|Arkansas|00068"
},
{
"path": "data-raw/zcta_county_rel_10.txt",
"chars": 6574059,
"preview": "ZCTA5,STATE,COUNTY,GEOID,POPPT,HUPT,AREAPT,AREALANDPT,ZPOP,ZHU,ZAREA,ZAREALAND,COPOP,COHU,COAREA,COAREALAND,ZPOPPCT,ZHUP"
},
{
"path": "man/address_ranges.Rd",
"chars": 2742,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transportation.R\n\\name{address_ranges}\n\\al"
},
{
"path": "man/alaska_native_regional_corporations.Rd",
"chars": 3031,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/native.R\n\\name{alaska_native_regional_corp"
},
{
"path": "man/append_geoid.Rd",
"chars": 921,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geocode.R\n\\name{append_geoid}\n\\alias{appen"
},
{
"path": "man/area_water.Rd",
"chars": 2997,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/water.R\n\\name{area_water}\n\\alias{area_wate"
},
{
"path": "man/block_groups.Rd",
"chars": 4985,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{block_groups}\n\\a"
},
{
"path": "man/blocks.Rd",
"chars": 4383,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{blocks}\n\\alias{b"
},
{
"path": "man/call_geolocator.Rd",
"chars": 719,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geocode.R\n\\name{call_geolocator}\n\\alias{ca"
},
{
"path": "man/call_geolocator_latlon.Rd",
"chars": 926,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geocode.R\n\\name{call_geolocator_latlon}\n\\a"
},
{
"path": "man/coastline.Rd",
"chars": 2250,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/water.R\n\\name{coastline}\n\\alias{coastline}"
},
{
"path": "man/combined_statistical_areas.Rd",
"chars": 3060,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/metro_areas.R\n\\name{combined_statistical_a"
},
{
"path": "man/congressional_districts.Rd",
"chars": 4849,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/legislative.R\n\\name{congressional_district"
},
{
"path": "man/core_based_statistical_areas.Rd",
"chars": 3394,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/metro_areas.R\n\\name{core_based_statistical"
},
{
"path": "man/counties.Rd",
"chars": 5085,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{counties}\n\\alias"
},
{
"path": "man/county_subdivisions.Rd",
"chars": 3522,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{county_subdivisi"
},
{
"path": "man/divisions.Rd",
"chars": 2665,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/national.R\n\\name{divisions}\n\\alias{divisio"
},
{
"path": "man/erase_water.Rd",
"chars": 2841,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{erase_water}\n\\alias{erase_"
},
{
"path": "man/filter_place.Rd",
"chars": 667,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/places.R\n\\name{filter_place}\n\\alias{filter"
},
{
"path": "man/filter_state.Rd",
"chars": 658,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/states.R\n\\name{filter_state}\n\\alias{filter"
},
{
"path": "man/fips_codes.Rd",
"chars": 990,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/fips_codes.R\n\\docType{data}\n\\name{fips_cod"
},
{
"path": "man/geo_join.Rd",
"chars": 1708,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{geo_join}\n\\alias{geo_join}"
},
{
"path": "man/grep_place.Rd",
"chars": 545,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/places.R\n\\name{grep_place}\n\\alias{grep_pla"
},
{
"path": "man/grep_state.Rd",
"chars": 536,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/states.R\n\\name{grep_state}\n\\alias{grep_sta"
},
{
"path": "man/is_tigris.Rd",
"chars": 403,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{is_tigris}\n\\alias{is_tigri"
},
{
"path": "man/landmarks.Rd",
"chars": 3894,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/landmarks.R\n\\name{landmarks}\n\\alias{landma"
},
{
"path": "man/linear_water.Rd",
"chars": 3205,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/water.R\n\\name{linear_water}\n\\alias{linear_"
},
{
"path": "man/list_counties.Rd",
"chars": 578,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{list_counties}\n\\alias{list"
},
{
"path": "man/list_places.Rd",
"chars": 525,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/places.R\n\\name{list_places}\n\\alias{list_pl"
},
{
"path": "man/list_states.Rd",
"chars": 515,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/states.R\n\\name{list_states}\n\\alias{list_st"
},
{
"path": "man/load_tiger.Rd",
"chars": 2049,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{load_tiger}\n\\alias{load_ti"
},
{
"path": "man/load_tiger_doc_template.Rd",
"chars": 2426,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{load_tiger_doc_template}\n\\"
},
{
"path": "man/lookup_code.Rd",
"chars": 1409,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{lookup_code}\n\\alias{lookup"
},
{
"path": "man/metro_divisions.Rd",
"chars": 2598,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/metro_areas.R\n\\name{metro_divisions}\n\\alia"
},
{
"path": "man/military.Rd",
"chars": 3147,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/landmarks.R\n\\name{military}\n\\alias{militar"
},
{
"path": "man/nation.Rd",
"chars": 2618,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/national.R\n\\name{nation}\n\\alias{nation}\n\\t"
},
{
"path": "man/native_areas.Rd",
"chars": 3380,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/native.R\n\\name{native_areas}\n\\alias{native"
},
{
"path": "man/new_england.Rd",
"chars": 3745,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/metro_areas.R\n\\name{new_england}\n\\alias{ne"
},
{
"path": "man/places.Rd",
"chars": 3846,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/places.R\n\\name{places}\n\\alias{places}\n\\tit"
},
{
"path": "man/primary_roads.Rd",
"chars": 3594,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transportation.R\n\\name{primary_roads}\n\\ali"
},
{
"path": "man/primary_secondary_roads.Rd",
"chars": 4070,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transportation.R\n\\name{primary_secondary_r"
},
{
"path": "man/pumas.Rd",
"chars": 4071,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/pumas.R\n\\name{pumas}\n\\alias{pumas}\n\\title{"
},
{
"path": "man/rails.Rd",
"chars": 2581,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transportation.R\n\\name{rails}\n\\alias{rails"
},
{
"path": "man/rbind_tigris.Rd",
"chars": 616,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{rbind_tigris}\n\\alias{rbind"
},
{
"path": "man/regions.Rd",
"chars": 2653,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/national.R\n\\name{regions}\n\\alias{regions}\n"
},
{
"path": "man/roads.Rd",
"chars": 4014,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transportation.R\n\\name{roads}\n\\alias{roads"
},
{
"path": "man/school_districts.Rd",
"chars": 4566,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{school_districts"
},
{
"path": "man/shift_geometry.Rd",
"chars": 4180,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/shift_geometry.R\n\\name{shift_geometry}\n\\al"
},
{
"path": "man/state_legislative_districts.Rd",
"chars": 3632,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/legislative.R\n\\name{state_legislative_dist"
},
{
"path": "man/states.Rd",
"chars": 3447,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/states.R\n\\name{states}\n\\alias{states}\n\\tit"
},
{
"path": "man/tigris-exports.Rd",
"chars": 245,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/tigris-package.R\n\\name{tigris-exports}\n\\al"
},
{
"path": "man/tigris-package.Rd",
"chars": 2870,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/tigris-package.R\n\\docType{package}\n\\name{t"
},
{
"path": "man/tigris_cache_dir.Rd",
"chars": 999,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{tigris_cache_dir}\n\\alias{t"
},
{
"path": "man/tigris_type.Rd",
"chars": 460,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/helpers.R\n\\name{tigris_type}\n\\alias{tigris"
},
{
"path": "man/tracts.Rd",
"chars": 5211,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{tracts}\n\\alias{t"
},
{
"path": "man/tribal_block_groups.Rd",
"chars": 3967,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/native.R\n\\name{tribal_block_groups}\n\\alias"
},
{
"path": "man/tribal_census_tracts.Rd",
"chars": 3581,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/native.R\n\\name{tribal_census_tracts}\n\\alia"
},
{
"path": "man/tribal_subdivisions_national.Rd",
"chars": 3205,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/native.R\n\\name{tribal_subdivisions_nationa"
},
{
"path": "man/urban_areas.Rd",
"chars": 3028,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/metro_areas.R\n\\name{urban_areas}\n\\alias{ur"
},
{
"path": "man/validate_county.Rd",
"chars": 1988,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{validate_county}\n\\alias{vali"
},
{
"path": "man/validate_state.Rd",
"chars": 1862,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{validate_state}\n\\alias{valid"
},
{
"path": "man/voting_districts.Rd",
"chars": 4294,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/legislative.R\n\\name{voting_districts}\n\\ali"
},
{
"path": "man/zctas.Rd",
"chars": 3945,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/enumeration_units.R\n\\name{zctas}\n\\alias{zc"
},
{
"path": "tests/testthat/_snaps/enumeration_units.md",
"chars": 16120,
"preview": "# enumeration unit functions work\n\n Code\n counties(cb = TRUE, progress_bar = FALSE)\n Message\n Retrieving"
},
{
"path": "tests/testthat/_snaps/landmarks.md",
"chars": 5128,
"preview": "# landmarks works\n\n Code\n area_landmarks\n Output\n Simple feature collection with 530 features and 10 fie"
},
{
"path": "tests/testthat/test-enumeration_units.R",
"chars": 3130,
"preview": "test_that(\"enumeration unit functions work\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_ca"
},
{
"path": "tests/testthat/test-geocode.R",
"chars": 303,
"preview": "test_that(\"call_geolocator works\", {\n skip_on_cran()\n skip_on_ci()\n expect_identical(\n call_geolocator(\"3700 Koppe"
},
{
"path": "tests/testthat/test-landmarks.R",
"chars": 698,
"preview": "test_that(\"landmarks errors\", {\n skip_on_cran()\n skip_on_ci()\n expect_error(landmarks(state = \"WY\", type = \"pont\"))\n}"
},
{
"path": "tests/testthat/test-legislative.R",
"chars": 4189,
"preview": "test_that(\"congressional_districts warns and errors\", {\n skip_on_cran()\n skip_on_ci()\n # TODO: Enable if warning for "
},
{
"path": "tests/testthat/test-lookup_helper.R",
"chars": 601,
"preview": "test_that(\"State lookup works\", {\n expect_equal(lookup_code(\"me\"), \"The code for Maine is '23'.\")\n expect_equal(lookup"
},
{
"path": "tests/testthat/test-metro_areas.R",
"chars": 1521,
"preview": "test_that(\"metro areas functions work\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_cache ="
},
{
"path": "tests/testthat/test-national.R",
"chars": 407,
"preview": "test_that(\"nation errors\", {\n skip_on_cran()\n skip_on_ci()\n expect_error(nation(resolution = \"500K\"))\n})\n\ntest_that(\""
},
{
"path": "tests/testthat/test-native.R",
"chars": 1398,
"preview": "test_that(\"native functions work\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_cache = TRUE"
},
{
"path": "tests/testthat/test-places.R",
"chars": 840,
"preview": "test_that(\"places errors\", {\n skip_on_cran()\n skip_on_ci()\n expect_error(places(year = 2018))\n expect_error(places(y"
},
{
"path": "tests/testthat/test-pumas.R",
"chars": 737,
"preview": "test_that(\"pumas works\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_cache = TRUE))\n expec"
},
{
"path": "tests/testthat/test-shift_geometry.R",
"chars": 175,
"preview": "test_that(\"shift_geometry works\", {\n skip_on_cran()\n skip_on_ci()\n us_states <- states(cb = TRUE, resolution = \"20m\")"
},
{
"path": "tests/testthat/test-states.R",
"chars": 889,
"preview": "test_that(\"states works\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_cache = TRUE))\n\n exp"
},
{
"path": "tests/testthat/test-transportation.R",
"chars": 728,
"preview": "test_that(\"transportation functions work\", {\n skip_on_cran()\n skip_on_ci()\n withr::local_options(list(tigris_use_cach"
},
{
"path": "tests/testthat/test-water.R",
"chars": 1016,
"preview": "test_that(\"water functions error\", {\n skip_on_cran()\n skip_on_ci()\n state <- \"NOH\"\n expect_error(\n suppressWarnin"
},
{
"path": "tests/testthat/test_lookup_helper.R",
"chars": 689,
"preview": "test_that(\"State lookup works\", {\n skip_on_cran()\n skip_on_ci()\n expect_identical(lookup_code(\"me\"), \"The code for Ma"
},
{
"path": "tests/testthat.R",
"chars": 56,
"preview": "library(testthat)\nlibrary(tigris)\n\ntest_check(\"tigris\")\n"
},
{
"path": "tigris.Rproj",
"chars": 542,
"preview": "Version: 1.0\nProjectId: 6538395f-dbf9-41a9-987c-287a4f32a92d\n\nRestoreWorkspace: Default\nSaveWorkspace: Default\nAlwaysSav"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the walkerke/tigris GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 114 files (6.8 MB), approximately 1.8M tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.