Isochrone-Based Area-Weighted ACS Aggregation
Overview
Computes American Community Survey (ACS) estimates for the area within a given drive time of each of a set of points, such as the locations of pre-kindergarten classrooms. Such an area is called an isochrone. The drive-time areas come from a routing service, either the 'Open Source Routing Machine' ('OSRM', https://project-osrm.org/) or 'openrouteservice' (https://openrouteservice.org/), and the ACS 5-year estimates of census tracts come from the Census Bureau (https://www.census.gov/data/developers.html) through the 'tidycensus' package, one state at a time. The tracts that overlap an area are combined by area weighting, which uses two weights: the share of each tract's area that lies inside, for counts and rates, and each tract's share of the overlapping area, for the medians and per-person values of three ACS tables (median household income, median home value, and per capita income). A median or per-person value from any other table is added up like a count. Counts, medians, per-person values, and five rates are returned with a margin of error at a chosen confidence level, 90 percent by default, and with a record of the settings, inputs, and package versions behind the run. The five rates are the poverty rate, the shares of households receiving Supplemental Nutrition Assistance Program (SNAP) benefits and Supplemental Security Income, the unemployment rate, and the labor force participation rate. The margins of error of counts and rates use the approximation formulas in chapter 8 of U.S. Census Bureau (2020) "Understanding and Using American Community Survey Data: What All Data Users Need to Know" https://www.census.gov/programs-surveys/acs/library/handbooks/general.html. For a count the formula for a sum is applied to the weighted tract estimates, with the weights treated as fixed. For a rate the default is the formula for a ratio. Its margin of error is at least as wide as that of the formula for a proportion, which the handbook gives for ratios whose numerator is part of the denominator, as it is in all five rates. The margins of error of medians and per-person values are an approximation made by the package.
Changed defaults
cacs_isochrone(),cacs_acs_prefetch(), andcacs_intersect_weight(), and socacs_run(), now save their results in a folder inside the temporary folder of the R session, which R deletes when the session ends. Versions 0.5.1 and earlier saved them in the user cache folder of the operating system and kept them until they were deleted. To keep saved results between sessions, add this line to the R startup file:options(catchmentACS.cache_dir = tools::R_user_dir("catchmentACS", "cache")). A cache folder outside the temporary folder is tidied once per session: results not used for 30 days are deleted, andoptions(catchmentACS.cache_max_age_days = )sets another number of days. The package no longer reads or deletes the folder used by earlier versions;?cacs_cache_dirgives its location, and it can be deleted by hand. The packages memoise and rappdirs are no longer needed.
Show all changes in 0.6.0Hide the rest of the changes in 0.6.0
cacs_set_cache(scope = "global")no longer writes to the R startup file. It sets the option for the session and shows the line to add to the startup file.confirmis kept so that code written for earlier versions still runs, but it is not used.cacs_cache_dir()no longer creates the cache folder unlesscreate = TRUE.as_tibble()on acacs_run()result keeps the rows in their order by default.rate_first = TRUEputs the rate rows first within each site and drive time, andoptions(catchmentACS.rate_first_default = TRUE)does the same for conversions called from your own code, while conversions made inside other packages keep the order. As a result,dplyr::semi_join(),dplyr::anti_join(), and summaries afterdplyr::rowwise()return the right rows.- The map functions (
cacs_plot_site_isochrone(),cacs_plot_site_intersection(),cacs_plot_site_weighted(),cacs_plot_site_rates(), andcacs_plot_site_pipeline()) now draw the standard OpenStreetMap map by default (tiles = "OpenStreetMap"). The CARTO tiles used before need an API key, which these functions do not send, and they showed a notice asking for one. Any other provider inleaflet::providerscan still be chosen withtiles.
Bug fixes
cacs_intersect_weight()andcacs_run(acs = )now treat the Census Bureau's annotation codes (-222222222, -333333333, -555555555, -666666666, -888888888, and -999999999) in the estimates and margins of error of ACS data given to them as missing, with a warning that names the codes found; they used to enter the sums. A code in place of a margin of error therefore makes that margin of errorNA, and a rate that uses the variableNAas well. Data fromcacs_acs_prefetch()and the bundled data give the same results as before.cacs_acs_validate(),cacs_intersect_weight(),cacs_run(acs = ), andcacs_acs_prefetch()now stop with an error when a tract has two rows for the same variable; such a row used to be added twice.cacs_intersect_weight(), andcacs_run()through it, now recognize saved results by the drive-time areas themselves, so a subset or an edited copy of acacs_isochrone()result no longer returns rows saved for another subset. The key also no longer depends on how the row names of the areas are stored. Results saved by earlier versions are computed again once.cacs_isochrone()now stops at the first site that gets HTTP status 429, 401, or 403 and sends no request for the remaining sites; before, it tried every site first.cacs_isochrone()no longer reads a port number in a connection error, such as "port 443", as an HTTP status. A connection failure or a timeout is therefore tried again, up to three times, as the help page describes; before, the site was not tried again.cacs_acs_prefetch()likewise no longer reads a port number or a waiting time in a connection error as an HTTP status. A connection failure is tried up to three times and then stops with an error of classcatchmentACS_error_network; before, it stopped at once with an error saying that the Census Bureau had refused the request.cacs_isochrone()no longer saves a result in which routing failed for a site in a way that may be temporary (no answer, a timeout, or an HTTP 5xx status), and it does not use such a result saved by an earlier version, so a temporary failure is not returned again from the cache. A site that the routing service rejects with another HTTP 4xx status is saved with the result, and a warning says so when the saved result is used.- A server set with
options(osrm.server = )now stays in use over repeatedcacs_isochrone()calls; before, loading the osrm package during the first call replaced it with the public demo server for later calls, and the record kept with the result named that server. cacs_acs_prefetch(), and socacs_run(), no longer stops with "package lwgeom required" when spherical geometry is turned off withsf::sf_use_s2(FALSE): the check for tracts without area now measures the tracts in EPSG:5070 in that case, so the lwgeom package is not needed.cacs_intersect_weight(), and socacs_run(), now leaves the optionsf_use_s2as it was. It turns spherical geometry off while it runs, as before, but it used to set the option toTRUEafterwards when the option had not been set.cacs_run(output = "list_column")no longer gives the warningsUnknown or uninitialised columnwhensitesis an sf object built on a tibble withoutlonandlatcolumns. The two columns of the result areNA, as before, and are read only from columns with exactly these names.cacs_acs_prefetch()now reads back a result it saved together with its message about removed water tracts also when the package is installed with its sources kept (for example withR_KEEP_PKG_SOURCE=yes). The saved message kept a reference to the package source that changed when the file was read, so the saved copy never matched its checksum file and each call downloaded the data again.- The map functions now find the bundled
cacs_alabama_sitestable when they are called ascatchmentACS::withoutlibrary(catchmentACS), and an object of the same name in the global environment no longer takes its place. cacs_derive_rates()now gives an error for an argument passed through..., such aslevel = 0.95, which it used to ignore; the confidence level is set incacs_propagate_moe().cacs_intersect_weight(), and socacs_run(), now stops with an error of classcatchmentACS_error_geometrywhen the geometry of no row of the drive-time areas or of the tracts can be repaired; before, an error in writing the message took its place.cacs_summary_as_markdown()now names the confidence level of the result in the caption ofrates_per_site_moe, which always said 90%;summary()records the level on that table.
Other changes
cacs_intersect_weight()has a new argumentcache_dir, ascacs_isochrone()andcacs_acs_prefetch()have, andcacs_run(cache_dir = )now applies to all three steps.cacs_clear_cache()andcacs_cache_status()now handle only the files named the way the package names its saved files, and they include the GeoPackage files written bycacs_acs_prefetch(write_gpkg = TRUE).cacs_clear_cache(confirm = TRUE)in a non-interactive session now says that it deleted nothing because it could not ask for confirmation.- The
phasevalues thatcacs_capture_conditions()returns for conditions fromcacs_run(),cacs_derive_rates(), andcacs_propagate_moe()are now"run","rates", and"moe"; before, they were longer labels that began with a section number of an internal design document. Several warnings and messages that had nophasenow have the name of their step, such as"isochrone"or"intersect". - Error, warning, and progress messages were rewritten to say what happened and what to do. They no longer refer to development versions, to sections of an internal design document, or to functions and arguments that do not exist (such as
cacs_derive_rates_custom()andcrs_area). The messages about the OSRMresvalue used whenresis not given say which value was used and how to choose another. The condition classes are unchanged. cacs_validate_iso()gives plainerfix_hintandexpectedtext for ring topology, provider values, and missing columns. Thecheckvalues and the columns of the table are unchanged.- The suggested packages mapboxapi, r5r, httptest2, covr, lintr, pkgdown, and roxygen2 were dropped; none of them was used by the package. Building the vignettes needs knitr 1.35 or later.
- The warning of
cacs_derive_rates()about rates that areNAor use a replacement formula no longer names an internal function as its call. It names the call ofcacs_derive_rates(), or no call whencacs_run()calls it. - A
cacs_run(output = "list_column")result no longer has the attributeiso_was_filled, which was used only inside the package.
Documentation
- The vignettes are R Markdown documents built with knitr instead of Quarto documents, so building the package no longer needs the Quarto command-line tool. Their formulas are written as MathML: in the vignettes opened with
vignette(), longer formulas were shown as TeX code before and are now displayed as formulas, also without an internet connection. - Every exported topic has an example that runs;
?cacs_isochroneand?cacs_acs_prefetchshow results of those functions stored in the package. - The help pages describe the changes above and, where they apply, the limitations below.
- The new file
COPYRIGHTSnames the bundled data files that hold OpenStreetMap or Census Bureau data and gives the notices for those data.
Known limitations
cacs_isochrone()andcacs_run()do not build drive-time areas withprovider = "mapbox"orprovider = "r5r", which are not implemented and give an error, andcacs_derive_rates()accepts only the five built-in rates.cacs_isochrone(provider = "ors")has been checked only with simulated responses from openrouteservice.cacs_isochrone()sets no time limit on its requests. A routing server that accepts the connection but does not answer makes the call wait, and a server that cannot be reached is tried three times for each site, so a call with many sites can take minutes before it returns a result in which every site failed.cacs_validate_osrm_endpoint()checks an OSRM server with a time limit.cacs_acs_prefetch()downloads American Community Survey (ACS) 5-year estimates for the census tracts of one state per call.cacs_intersect_weight()andcacs_run()decide how to combine a variable from its ACS code alone. Codes in tables B19013 and B25077 are treated as medians, codes in table B19301 as per-person values, and every other code made of "B", five digits, an underscore, and three digits as a count, which is added up over the tracts. A median or per-person value with a code of that form from any other table therefore comes out as a sum of tract values, withweight_basis = "coverage"and no warning.- A rate from
cacs_derive_rates()orcacs_run()divides the total of its numerator by the total of its denominator, even when the two totals come from different tracts. This happens when the ACS data have a tract's row for one of the two codes but not for the other, for example after rows with a missing estimate were removed. The rate can then be far from the share for the area, even above 1, without a warning;n_tracts_numandn_tracts_denthen differ, unless the two codes lack the same number of tracts. - When the ACS data have no row for a tract and a variable,
cacs_intersect_weight()andcacs_run()leave that tract out of the variable's total or average without a warning, so a total comes out too small, andcacs_acs_validate()does not report the missing row.n_tractson that variable's row is then smaller than on the rows of the variables that have the tract. - The part of a drive-time area that has no tracts in the ACS data, such as the part across a state line, adds nothing: counts come out too small, and rates and medians come from the remaining tracts. The only warning compares the bounding box of all the drive-time areas with the bounding box of all the tracts, so it is not given when the uncovered part lies inside that box or reaches less than 0.05 degrees (about 5 km) beyond it.
- The drive-time areas in the example file
legacy_2025_isochrones.rdsare circles with a radius of 1 km per minute of driving, not areas computed by a routing service, yet their routing columns hold fixed values such asprovider = "osrm",routing_engine_version = "OSRM 5.27.1", andosm_snapshot_status = "explicit". Results computed from them therefore name OSRM as the provider, in their columns and in the output ofprint()andcacs_describe().
From NEWS.md in the release
Install
Health
- OK13 OKNow
- OK4 OK2026-10-06
Documentation
- Help pages
- 37 (1 internal)includes a package overview page
- Examples that run
- 100%36 run in a plain check (8 of them under a condition)
- Exported functions with examples
- 100%
- Documented parameters
- 96%
- Return-value docs
- 96%
- Help pages citing references
- 14%
- A worked example with Alabama Pre-K sites
- Area weighting of tract estimates
- Getting started with catchmentACS
- How the estimates are computed
- Mapping each step for one Birmingham site
- Margins of error for combined estimates
- Rates and their margins of error
- Routing services, API keys, and offline use
- Updating code written for version 0.3
- Updating code written for version 0.4
Show 1 moreHide 1 vignette
Downloads
Repository
9 development-tooling and community-health practices detected across 6 families in the upstream repository
Checks run against github.com/joonho112/catchmentacs on 2026-10-18.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-24 · The repository has a site deploy workflow
pkgdown site last built 2026-09-24, before release 0.6.0 (2026-10-06)
Show all practicesHide 2 practices
Dependencies
Code & Tests
Datasets
People & History
- 0.6.0Latest2026-10-06 · current release ·
2 days in CRAN's queue
Listed in CRAN's incoming queue from 2026-10-03 21:57 to 2026-10-06 01:12 UTC, in 11 readings. - RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-10-06
- Total releases
- 1 / 1 yrs
- License
- MIT + file LICENSE OSI
- Copyright
- see file COPYRIGHTS
- Minimum R
- ≥ 4.1.0
- Bundled data
- 1.4 KB / 2 files
- Download size
- 2.4 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("catchmentACS")The package provides a citation file that builds its entry when R runs it. Run citation() to see it.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-21, which the citation names so these numbers can be found later. More on citing and the projects behind them.