Skip to contents

Retrieves HUD Comprehensive Housing Affordability Strategy (CHAS) data, which cross-tabulate ACS housing-need measures (cost burden, overcrowding, and related housing problems) by tenure, household income relative to HUD Area Median Family Income (HAMFI), race/ethnicity, and household type. Data are drawn either from HUD's CHAS API (for "nation", "state", "county", "mcd", and "place" geographies) or from an on-disk parquet mirror on Box (for "tract"). Where a data dictionary is available, the source's terse column codes are expanded into descriptive snake_case names (see Details).

Usage

get_chas_housing_affordability(
  geography,
  end_year = 2022,
  state_code = NULL,
  entity_code = NULL,
  api = FALSE,
  directory_path = file.path(climateapi::get_box_path(), "built-environment", "hud",
    "comprehensive-housing-affordability-strategies"),
  columns = NULL
)

Arguments

geography

The geographic summary level. One of "nation", "state", "county", "mcd" (minor civil division), "place", or "tract". All levels except "tract" are served by the API (api = TRUE); "tract" is read from disk (api = FALSE).

end_year

The last year of the five-year ACS period, from 2009 to 2022. Defaults to 2022 (the most recent period).

state_code

A two-digit state FIPS code. Required by the API for every geography except "nation"; ignored for the disk (tract) path.

entity_code

A FIPS identifier for the requested sub-state geography (county, MCD, or place). Required by the API for those geographies; ignored for the disk (tract) path.

api

Logical. If TRUE, query the HUD API (requires a registered key; see register_hud_api_key()). If FALSE (the default), read from the on-disk parquet mirror – currently only "tract" is available this way.

directory_path

The directory containing the on-disk CHAS parquet files and the data dictionary. Defaults to the CHAS folder under the C&C Box path. Used for the disk (tract) path and for locating the dictionary used to rename columns.

columns

An optional character vector of raw column names to read from the parquet file (disk path only). Names refer to the source's original column codes, i.e. before the codebook renaming described in Details. geoid and year are always read, whether or not they are listed. If NULL (the default), all columns are read.

Value

A tibble of CHAS results, one row per geography. Estimate columns whose codes appear in the data dictionary are renamed to descriptive snake_case names built from the variable's definition, for example owner_occupied_income_lte_30_hamfi_cost_burden_gt_50. See get_chas_codebook() for the abbreviations these names use (lte, hh, ppr, and so on). All other columns (the geoid identifier, the year label, margin-of-error columns, and any column whose descriptive name is ambiguous among those returned) retain their original names. API results are returned with HUD's own column names unless they happen to match dictionary codes.

The result carries a "chas_codebook" attribute holding the tibble returned by get_chas_codebook() for the period used – one row per CHAS estimate variable, giving its descriptive name, source code, table, and definition. When no dictionary is available the attribute is a zero-row tibble of that same shape.

Details

CHAS releases cover five-year ACS periods; end_year is the last year of that period (e.g. end_year = 2021 is the 2017-2021 release).

The source writes every identifier with its summary level in front, separated by "US""1400000US01001020100" for a tract in recent releases, "14000US..." in releases through 2015-2019, and "08000US..." in the tract-part files. That prefix is removed, so geoid is the plain eleven-digit tract identifier used by tigris::tracts() and by tidycensus, and joins to them without further work.

For 2009-2012, the source publishes counts for census tract parts rather than whole tracts. Each part identifier is state, county, county subdivision, place, and tract, so the tract is taken from the state, county, and final six digits, and the parts are summed to whole-tract counts. These years return the same geoid column as every other year (earlier versions of this function returned a separate tract_geoid column that was not in fact a tract identifier).

Column renaming uses the CHAS data dictionary found under directory_path, read via get_chas_codebook(). The dictionary's hierarchical descriptions are collapsed into a single descriptive snake_case name per column and applied to any matching columns; columns without a dictionary match (including margin-of-error columns, which the dictionary does not describe separately) keep their original names. If no dictionary is found (for example, when querying the API without the Box mirror synced), the data are returned with the source's original column names. If a dictionary is found for a different period than the one requested, get_chas_codebook() warns and the substituted period is recorded in the codebook's vintage column.

That codebook is attached to the returned data as an attribute named "chas_codebook", so the definition of any column can be looked up without reading the dictionary from disk again:

chas = get_chas_housing_affordability(geography = "tract", end_year = 2021)
codebook = attr(chas, "chas_codebook")

The attribute holds the whole codebook for the period, including variables not present in the returned columns. Most data-manipulation functions drop attributes they do not recognize, so save the codebook to its own object before reshaping, joining, or filtering the data.

Descriptive names are unique within a CHAS table but repeat across tables, since each table has its own "owner occupied" total and the like. A name is therefore treated as ambiguous only when it describes more than one of the columns actually being returned; those columns keep their original names and a message reports how many. In practice this means requesting a single table always renames cleanly, while requesting the whole file leaves a small number of top-level totals unrenamed. Use get_chas_codebook() to look up what any column means.

See also

get_chas_codebook() for the descriptive name and definition of every CHAS variable.

Examples

if (FALSE) { # \dontrun{
## tract-level data for the 2017-2021 period, read from the on-disk Box mirror
chas = get_chas_housing_affordability(geography = "tract", end_year = 2021)

## the definitions of the columns returned above
codebook = attr(chas, "chas_codebook")

## county-level data from the HUD API (requires a registered key)
register_hud_api_key("your-hud-api-key")
get_chas_housing_affordability(geography = "county", end_year = 2021, state_code = "01", entity_code = "001", api = TRUE)
} # }