Launch a small, locally-run Shiny app that visualizes the spatial
output of compile_acs_data() as an interactive choropleth map. Colors,
breaks, and popups are derived from the codebook attribute attached to the
input.
Usage
view_acs_data(
.data,
geography_extent,
variables = NULL,
geography = NULL,
target_geographies = NULL,
...
)Arguments
- .data
An
sfobject produced bycompile_acs_data()withspatial = TRUE. Must retain its"codebook"attribute.- geography_extent
Required. A character vector declaring which parent geographies are appropriate statistical benchmarks for
.data– any of"county","state","nation"(alias"national"), or"none"to disable benchmarking. The caller is responsible for this judgment: only declare"state", say, when.datacovers the full state(s) it spans. Declared levels are further filtered to those structurally valid for the observation geography (e.g. state-level data can only be benchmarked against the nation) and to those passing a basic coverage check: the"nation"benchmark requires all 51 states to be present;"state"requires more than one county per present state (single-county states such as DC are exempt); and"county"requires more than one tract/block group per present county. Levels failing these checks are dropped with a warning.- variables
Optional character vector restricting which variables appear in the picker. Accepts either raw column names (e.g.,
"race_nonhispanic_white_alone_percent") or pretty labels as produced bymake_pretty_names(). WhenNULL(default), all eligible numeric variables from the codebook are shown.- geography
Geography level of
.data, matching the value passed tocompile_acs_data(). Used to identify the observation level for benchmarking – it disambiguates 5-character county GEOIDs from ZCTA/CBSA codes of the same length. WhenNULL, the level is inferred from GEOID length where unambiguous (block group, tract, state); county-level data requires this argument for benchmarking.- target_geographies
Optional
sfpolygon object whose rows define target geographies onto which the source data are interpolated viainterpolate_acs()using area-weighted overlap. Must contain aGEOIDcolumn that uniquely identifies each polygon; an optionalNAMEcolumn is used in popups when present. When supplied (or once polygons are drawn in-app), a "Geography" toggle appears in the sidebar that switches the map between the source and the target dataset. Benchmark values remain computed from the source data; in Target view, each target polygon is mapped to a parent (county / state / national) by majority-area overlap.- ...
Forwarded to
shiny::runApp()(e.g.,port,host,launch.browser).
Value
A shiny.appobj (invisibly). When called from an interactive
session, the app is launched in the default browser.
Details
The map uses MapLibre via the mapgl package and the CARTO Positron basemap (no API token required). Color palettes default to those in the urbnthemes package (sequential cyan for counts/medians/averages, quintile cyan for percentages, diverging cyan/orange for index variables).
A variable picker is shown in the sidebar; if .data spans multiple years a
year picker is also shown. Below the picker an interactive histogram of the
selected variable is rendered, and users can drag a horizontal selection on
it to restrict the choropleth's color scale. Polygons whose value falls
outside the selected range render in neutral grey, and their popups note the
out-of-range status. The brushable range defaults to c(0, 1) for percent
variables and to the observed data range for everything else.
A "Statistical benchmark" dropdown appears when geography_extent declares
one or more parent geographies that are valid comparisons for .data and the
data pass a basic coverage check. It recolors the map by whether each
polygon's estimate is statistically significantly larger than, smaller than,
or indistinguishable from the chosen higher-geography benchmark. Block-group
and tract data can be benchmarked against their county or state, county data
against its state, and state data against the nation. Benchmark values are
aggregated from .data via interpolate_acs() (so the result may differ
slightly from a separately-pulled ACS estimate at that geography), and
significance is tested via tidycensus::significance() at the 90 percent
confidence level (matching the quantified survey error vignette). Variables
without a margin-of-error column fall back to the default coloring.
Regardless of target_geographies, the map carries a drawing toolbar at its
top-left with "Point", "Line", and "Polygon" tools. Each drawn feature gets a
text field in the sidebar where it can be named; the names appear in popups
and the exported data. Draw one or more polygons and click "Interpolate to
drawn area" in the sidebar to interpolate the source data onto them via
interpolate_acs(); the map then switches to a "Target" view of the result,
and benchmarking (if available) compares each drawn polygon to the parent
geography it mostly overlaps. "Clear target" discards the drawn polygons,
reverting to target_geographies when one was supplied and otherwise to the
source view.
Interpolation is only accurate where a target polygon is fully covered by the
source geographies. Any drawn polygon (or supplied target_geographies row)
that extends beyond the source extent cannot be accurately interpolated, so
its values are set to NA (rendered in neutral grey) and a warning is shown
in the app.
A "Download" section in the sidebar offers two downloads. "Download data"
opens a dialog to pick a file format – CSV, GeoPackage (.gpkg), GeoJSON,
GeoParquet (.parquet), or non-spatial Parquet (.parquet) – and, when an
interpolated (target) dataset exists, whether to export the interpolated
geographies only or those plus the source geographies (distinguished by a
geography_type column). The spatial formats retain geometry (and, in Target
view, the user-supplied names of the drawn geographies); the export includes
each variable's margin of error (<var>_M columns) and, when a statistical
benchmark is selected, the benchmark value, its margin of error, and the
significance category for the selected variable. GeoParquet requires the
sfarrow package and non-spatial Parquet requires arrow; if a chosen
format's packages aren't installed, the data is written to CSV instead.
"Download figure" opens a dialog for choosing an
export resolution (1x-4x the on-screen size), then saves the live map exactly
as displayed – basemap, active layer, current zoom and pan, and any drawn
areas – as a .png. The capture is performed in the browser, so it works
only in an interactive (locally-run) session.
The sidebar is organized into collapsible sections – "Data" (variable, year, statistical benchmark, and the data-distribution histogram), "Interpolate" (the source/target toggle and custom-geography drawing/naming), "Visual parameters", and "Download" – with only "Data" open at launch. The "Interpolate" section auto-expands whenever a polygon is drawn.
The "Visual parameters" section exposes display controls that don't change the data: a polygon-opacity slider, a legend-title override (blank uses the variable's pretty name), a basemap picker (CARTO Positron / Dark Matter / Voyager plus tokenless ESRI satellite and OpenTopoMap topographic rasters), and checkboxes that toggle a scale bar and a cardinal-direction compass (with N/E/S/W labels and an "N" over the north arrow; click it to reset north). A layers toggle at the map's bottom-right separately shows or hides the base-geography choropleth and any drawn features.
view_acs_data() requires the shiny, mapgl, bslib, and ggplot2
packages. These are listed in Suggests and checked at runtime.
Examples
if (FALSE) { # \dontrun{
df = compile_acs_data(
tables = c("race", "snap"),
years = 2022,
geography = "tract",
states = "NJ",
spatial = TRUE)
## `df` is a full-state NJ tract pull, so county and state are valid benchmarks.
view_acs_data(df, geography = "tract", geography_extent = c("county", "state"))
## Restrict the picker to a few variables:
view_acs_data(df, geography = "tract", geography_extent = c("county", "state"),
variables = c("snap_received_percent",
"race_nonhispanic_white_alone_percent"))
## Disable benchmarking (e.g. when the data are only a partial extent):
view_acs_data(df, geography = "tract", geography_extent = "none")
## Interpolate onto custom target polygons (e.g., neighborhoods):
neighborhoods = sf::st_read("path/to/neighborhoods.geojson")
# neighborhoods must have a `GEOID` column identifying each polygon.
view_acs_data(df, geography = "tract", geography_extent = c("county", "state"),
target_geographies = neighborhoods)
} # }