---
title: "Find EPA walkability values for pre-geocoded addresses"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Find EPA walkability values for pre-geocoded addresses}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
library(actiwalkability)
```

The EPA National Walkability Index is reported for Census block groups.  That
makes a Census block-group GEOID (the 12-character `GEOID10` value) the useful
link between an address-level data set and the EPA layer.

This vignette starts after geocoding: it uses a small address lookup that
already contains a GEOID.  It therefore does not send any addresses to a
geocoding service and does not require a geocoding package.

## Start with an address-to-GEOID lookup

Keep addresses and GEOIDs as character vectors.  In particular, a GEOID must
not be converted to a number because leading zeroes are meaningful.

```{r addresses}
addresses <- dplyr::tibble(
  address_id = c("address_1", "address_2", "address_3"),
  address = c(
    "Pre-geocoded address in Baltimore County, MD",
    "Pre-geocoded address in Baltimore County, MD",
    "Pre-geocoded address in Baltimore City, MD"
  ),
  geoid = c("240054519002", "240054026041", "245102303002")
)

addresses
```

The GEOIDs in this example are Census 2010 block-group identifiers, which is
the geography used by the EPA layer queried by `acti_epa_walkability()`.
When a source instead provides state, county, tract, and block identifiers,
`acti_fips12()` can construct the block-group GEOID:

```{r make-geoid}
acti_fips12(state = 24, county = 510, tract = 60400, block = 2002)
```

## Query the EPA layer

Pass the unique GEOIDs to `acti_epa_walkability()`.  Setting `geometry = FALSE`
keeps the request small when only the index attributes are needed.  This call
uses the live EPA ArcGIS service, so it is left unevaluated when the vignette is
built.

```{r query-epa, eval = FALSE}
walkability <- acti_epa_walkability(
  unique(addresses$geoid),
  geometry = FALSE
)

walkability
```

The returned data include `GEOID10`, `NatWalkInd`, and, when the index is
available, `cat_walk_index`.  `cat_walk_index` is a four-level categorization
created from the EPA national walkability index breaks.  The EPA service may
also return other layer attributes.

## Attach values back to addresses

Join on the two character GEOID fields.  Keeping all address rows retains
multiple addresses within the same block group.

```{r join-back, eval = FALSE}
address_walkability <- dplyr::left_join(
  addresses,
  walkability,
  by = c("geoid" = "GEOID10")
)

dplyr::select(
  address_walkability,
  address_id, address, geoid, NatWalkInd, cat_walk_index
)
```

## Geocoding is a separate step and Census vintage matters

This package deliberately consumes GEOIDs rather than geocoding street
addresses.  Prepare and quality-check the address-to-GEOID crosswalk upstream,
then use the workflow above.  For projects that need a Census-geocoder client,
[`censusxy`](https://github.com/chris-prener/censusxy) is one option: it calls
the U.S. Census Bureau Geocoding Tools and is designed to batch unique
addresses.  Its repository notes that it is no longer under active development
as of early 2025, so check its current status and validate matches before using
it in a production workflow.

`censusxy` does not return columns named `GEOID10` or `GEOID20`.  With
`return = "geographies"`, it returns Census geography components such as
`cxy_state_id`, `cxy_county_id`, `cxy_tract_id`, and `cxy_block_id`; its
`vintage` argument determines the Census geography vintage.  A block-group
GEOID can then be constructed from those components with `acti_fips12()`.  Do
not run the following code as part of this package's workflow: it is an
illustration of a possible upstream geocoding step and requires `censusxy`.

```{r censusxy-example, eval = FALSE}
geocoded <- censusxy::cxy_geocode(
  address_data,
  street = "street",
  city = "city",
  state = "state",
  zip = "zip",
  return = "geographies",
  vintage = "Census2010_Current"
)

geocoded$geoid <- acti_fips12(
  geocoded$cxy_state_id,
  geocoded$cxy_county_id,
  geocoded$cxy_tract_id,
  geocoded$cxy_block_id
)
```

Here, the `10` and `20` suffixes mean *Census boundary vintage*, not GEOID
length: both a 2010 and a 2020 block-group identifier contain 12 digits.  The
EPA Walkability Index layer is based on Census 2010 block groups, and this
package intentionally queries and joins its non-null, 12-character `GEOID10`
field.  The same layer also exposes a nullable `GEOID20` field, but its alias
describes a “Census block group 12-digit FIPS code (2018)” and its declared
length is 50.  Those contradictory labels do not establish a reliable Census
2020 key.  Consequently, `GEOID20` is not used by this package.  The Census
Geocoder currently offers the `Census2010_Current` geography vintage for its
current benchmark; otherwise, a 2020-vintage result should be converted with an
appropriate Census crosswalk before it is joined to this EPA release.  Never
treat similarly shaped 12-digit identifiers from different vintages as
interchangeable.

Other approaches include calling the
[Census Geocoder API](https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.html)
directly, using a local or commercial geocoder, or obtaining GEOIDs from a
trusted data provider.  Regardless of the method, confirm that the result is a
12-character Census 2010 block-group GEOID before passing it to
`acti_epa_walkability()`.

## Requesting other EPA attributes or a study area

The EPA service exposes more than the overall `NatWalkInd` score.  Of particular
interest are the four inputs used to create it: `D2A_EPHHM` (employment and
household density), `D2B_E8MIXA` (employment and household mix), `D3b`
(street-intersection density), and `D4a` (distance to the nearest transit stop).
The matching `*_Ranked` fields provide their national ranks.  Population,
household, worker, land-area, and metropolitan-area fields are also useful for
describing or screening the returned block groups.

All `arcgislayers::arc_select()` arguments can be passed through
`acti_epa_walkability()`.  For example, use `fields` to limit the attributes
downloaded, or `filter_geom` and `predicate` to select block groups that
intersect a study-area geometry.  Do not call `acti_epa_walkability(NULL)`
without a spatial filter: it requests the entire national layer.

```{r selected-fields, eval = FALSE}
study_area_walkability <- acti_epa_walkability(
  geoid = NULL,
  geometry = FALSE,
  filter_geom = study_area,
  predicate = "intersects",
  fields = c("GEOID10", "NatWalkInd", "D2A_EPHHM", "D2B_E8MIXA", "D3b", "D4a")
)
```
