tidycensus is the right tool for downloading ACS
estimates and margins of error. acsmoe starts after that:
it works with estimate/MOE columns that you already have.
Kyle Walker’s tidycensus article on ACS margins of error
shows the standard workflow and the standard Census approximation
formulas: https://walker-data.com/tidycensus/articles/margins-of-error.html.
That article demonstrates tidycensus::moe_sum(),
tidycensus::moe_prop(),
tidycensus::moe_ratio(), and
tidycensus::moe_product(). It also quotes the Census
warning that these approximation methods do not account for correlation
or covariance between basic estimates. acsmoe is intended
for the same tabular ACS regime, but exposes covariance-aware extensions
and a grouped aggregation helper.
This example mirrors the shape of Walker’s MOE vignette: pull tract-level ACS age-by-sex cells, then aggregate those cells into a derived total. The call is not evaluated in this vignette because it requires network access and, in many setups, a Census API key.
library(tidycensus)
library(dplyr)
library(acsmoe)
vars <- paste0("B01001_0", c(20:25, 44:49))
ramsey <- get_acs(
geography = "tract",
variables = vars,
state = "MN",
county = "Ramsey",
year = 2016
)
ramsey65 <- ramsey |>
group_by(GEOID) |>
summarize(
estimate_65plus = sum(estimate),
moe_65plus = acs_sum(estimate, moe)$moe,
.groups = "drop"
)With no covariance supplied, acs_sum() intentionally
reduces to the same zero-covariance root-sum-square calculation used by
tidycensus::moe_sum(). That makes it a drop-in bridge from
the standard workflow to more explicit uncertainty propagation.
The package website includes a fuller tidycensus example
with evaluated maps when the site is built with Census API credentials.
That example is kept out of CRAN vignette evaluation because it requires
network access, sf geometries, and current ACS API
availability.
Many ACS workflows become wide after
tidycensus::get_acs(output = "wide"), or after a
user-created join. acs_aggregate() handles this
paired-column form.
library(acsmoe)
tracts <- data.frame(
region = c("north", "north", "south", "south"),
population = c(1000, 1200, 900, 1100),
population_moe = c(120, 140, 100, 130),
households = c(420, 500, 360, 440),
households_moe = c(60, 70, 50, 65)
)
acs_aggregate(
tracts,
group_var = "region",
value_cols = c("population", "households"),
moe_cols = c("population_moe", "households_moe")
)
#> region population population_moe households households_moe
#> 1 north 2200 184.3909 920 92.19544
#> 2 south 2000 164.0122 800 82.00610The default cov_strategy = "zero" is deliberately
conservative in the API sense: it matches the standard Census
approximation behavior. It should not be read as a claim that tract
estimates are truly independent.
If a covariance matrix is available from an external method, pass it on the standard-error scale. Do not pass covariance of MOEs.
estimates <- c(1000, 1200)
moes <- c(120, 140)
ses <- moe_to_se(moes)
cov_mat <- matrix(
c(ses[1]^2, 1500,
1500, ses[2]^2),
nrow = 2
)
acs_sum(estimates, moes, cov = cov_mat)
#> estimate moe se
#> 1 2200 205.2234 124.7669For aggregation, cov_strategy = "constant" accepts a
scalar correlation and constructs a valid covariance matrix from the
input MOEs. This is useful for sensitivity analysis, not as an automatic
estimator of ACS covariance.
acsmoe does not download ACS data. Use
tidycensus for that.
acsmoe does not estimate variance from microdata. Use
survey or srvyr for PUMS and replicate-weight
workflows.
acsmoe also does not implement regionalization. Walker’s
tidycensus MOE article points readers to Spielman and
Folch’s regionalization work and an old Python implementation. That
historical code lives at https://github.com/geoss/censumander. We used it as
development-only reference material for formula checks, but
regionalization itself is out of scope for this package.
The boundary is intentional: acsmoe focuses on
propagation of uncertainty for tabular estimate/MOE workflows after ACS
data have already been obtained.
tidycensus: Load
US Census Boundary and Attribute Data as tidyverse and
sf-Ready Data Frames. https://CRAN.R-project.org/package=tidycensusgeoss/censumander. Historical Python reference
implementation used here only for development validation. https://github.com/geoss/censumander