| Type: | Package |
| Title: | Grab Longitudinal Employer-Household Dynamics (LEHD) Flat Files |
| Version: | 1.2.0 |
| Maintainer: | Jamaal Green <jamaal.green@gmail.com> |
| Description: | Designed to query Longitudinal Employer-Household Dynamics (LEHD) workplace/residential association and origin-destination flat files and optionally aggregate Census block-level data to block group, tract, county, or state. Also provides analytical functions for commute flow statistics, longitudinal change, and earnings tier distributions. Data comes from the LODES FTP server https://lehd.ces.census.gov/data/lodes/LODES8/. |
| License: | MIT + file LICENSE |
| URL: | https://jamgreen.github.io/lehdr/, https://github.com/jamgreen/lehdr/ |
| BugReports: | https://github.com/jamgreen/lehdr/issues/ |
| Depends: | R (≥ 4.1.0) |
| Imports: | dplyr, glue, httr2, magrittr, readr, rlang, stringr, tidyr |
| Suggests: | ggplot2, knitr, pkgdown, rmarkdown, sf, testthat (≥ 3.0.0), tigris, withr |
| VignetteBuilder: | knitr |
| Config/testthat/edition: | 3 |
| Encoding: | UTF-8 |
| Language: | en |
| Config/roxygen2/version: | 8.1.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-08-22 17:31:34 UTC; elmue |
| Author: | Jamaal Green |
| Repository: | CRAN |
| Date/Publication: | 2026-08-22 18:30:12 UTC |
lehdr: Grab Longitudinal Employer-Household Dynamics (LEHD) Flat Files
Description
Designed to query Longitudinal Employer-Household Dynamics (LEHD) workplace/residential association and origin-destination flat files and optionally aggregate Census block-level data to block group, tract, county, or state. Also provides analytical functions for commute flow statistics, longitudinal change, and earnings tier distributions. Data comes from the LODES FTP server https://lehd.ces.census.gov/data/lodes/LODES8/.
Author(s)
Maintainer: Jamaal Green jamaal.green@gmail.com (ORCID)
Authors:
Jamaal Green jamaal.green@gmail.com (ORCID)
Liming Wang lmwang@pdx.edu
Dillon Mahmoudi dillonm@umbc.edu (ORCID)
Other contributors:
Matthew Rogers matthew.rogers09@gmail.com [contributor]
Kyle Walker kyle@walker-data.com [contributor]
Eli Pousson eli.pousson@gmail.com (ORCID) [contributor]
See Also
Useful links:
Report bugs at https://github.com/jamgreen/lehdr/issues/
Compute commute flow statistics from LODES OD data
Description
Derives three key commute flow metrics from an OD tibble: inflow, outflow, net flow, and the self-containment ratio. These metrics are widely used in transportation planning and economic geography to characterize labor market catchment areas and job/housing balance.
Self-containment is defined as the proportion of workers who both live and work within the same geographic unit, relative to all employed residents. A value close to 1 indicates a highly self-contained labor market; values near 0 indicate heavy out-commuting.
Net flow is defined as inbound workers minus outbound workers (including internal flows as both in and out). This is an unsigned flow balance indicator: positive values signal net job importers (more workers arrive than leave); negative values signal net exporters.
Cross-state commuters: When state_part = "main" is used in
grab_lodes(), only workers who live and work in the same state are
included. Workers who cross state lines (e.g., Maryland residents working
in DC) appear only in state_part = "aux" files for the workplace
state. To capture full commute flows for border counties, retrieve both
"main" and "aux" files and bind the rows before calling
compute_commute_stats().
Usage
compute_commute_stats(od_df, agg_geo = "tract")
Arguments
od_df |
A data frame (tibble) of LODES origin-destination data
returned by Note on row structure: LODES OD files are a flow matrix. A call to
|
agg_geo |
The geographic level of the OD data. Must match the level
at which |
Value
A tibble with one row per geography, containing:
{agg_geo}The geographic identifier.
yearYear of the data (if present in
od_df).stateState FIPS abbreviation (if present in
od_df).workers_inTotal workers arriving (working in this geography).
workers_outTotal workers departing (living here, working elsewhere).
workers_internalWorkers whose home and work are both in this geography (internal flows).
net_flowNet worker flow:
workers_in - workers_out. Positive values indicate net job importers.self_containmentShare of resident workers who also work in this geography:
workers_internal / workers_out_total, whereworkers_out_totalincludes internal flows.
Examples
## Not run:
od <- grab_lodes(
state = "md", year = 2019,
lodes_type = "od", job_type = "JT00",
segment = "S000", state_part = "main",
agg_geo = "county"
)
compute_commute_stats(od, agg_geo = "county")
## End(Not run)
Compute earnings tier shares from LODES RAC or WAC data
Description
Computes the share of jobs (or workers) in each of the three LODES monthly earnings tiers:
- Low (
CE01) Earnings up to $1,250/month.
- Mid (
CE02) Earnings $1,251-$3,333/month.
- High (
CE03) Earnings above $3,333/month.
Earnings shares are useful for tracking wage polarization, identifying
low-wage job concentration, and examining how the earnings structure of
a labor market has shifted over time, especially when combined with
compute_lodes_change().
The total denominator is the sum of the three tiers, ensuring shares sum to 1 within rounding error.
Usage
compute_earnings_share(
lodes_df,
type = c("wac", "rac"),
geo_col = NULL,
output = c("wide", "long")
)
Arguments
lodes_df |
A data frame (tibble) of LODES RAC or WAC data returned
by |
type |
One of |
geo_col |
The name of the geography column to group by, e.g.
|
output |
One of |
Value
A tibble with earnings tier counts and shares. In "wide" format,
columns are added for share_low, share_mid, and share_high. In
"long" format, columns are tier, label, count, and share.
Examples
## Not run:
wac <- grab_lodes(
state = "md", year = 2019,
lodes_type = "wac", job_type = "JT00",
segment = "S000", agg_geo = "county"
)
compute_earnings_share(wac, type = "wac", geo_col = "w_county")
# Long format, suitable for ggplot2
compute_earnings_share(
wac, type = "wac", geo_col = "w_county", output = "long"
)
## End(Not run)
Compute longitudinal change in LODES data across years
Description
Computes absolute and percentage change in LODES variables between two years for each geographic unit. This is particularly useful for tracking shifts in employment, industrial composition, or earnings structure over time.
Percentage change is computed as
(\text{compare} - \text{base}) / \text{base} \times 100.
Returns NA where base_value is zero or missing.
Usage
compute_lodes_change(
lodes_df,
geo_col = NULL,
base_year = NULL,
compare_year = NULL,
variables = NULL,
output = c("wide", "long")
)
Arguments
lodes_df |
A data frame (tibble) of LODES data covering at least two
years, as returned by |
geo_col |
The name of the geography column to group by, e.g.
|
base_year |
The reference year for computing change. Defaults to the
earliest year present in |
compare_year |
The target year for computing change. Defaults to the
latest year present in |
variables |
Optional character vector of numeric column names to
include in the output. Defaults to all numeric columns (excluding |
output |
One of |
Value
A tibble of change statistics. In "wide" format, columns follow
the pattern {variable}_base, {variable}_compare,
{variable}_change, and {variable}_pct_change. In "long" format,
columns are variable, base_value, compare_value, change, and
pct_change.
Examples
## Not run:
wac_multi <- grab_lodes(
state = "md", year = c(2015, 2019),
lodes_type = "wac", job_type = "JT00",
segment = "S000", agg_geo = "county"
)
compute_lodes_change(wac_multi, geo_col = "w_county")
# Long format
compute_lodes_change(
wac_multi,
geo_col = "w_county",
output = "long",
variables = c("C000", "CE01", "CE02", "CE03")
)
## End(Not run)
Download and load LODES geographic crosswalk into a data frame (tibble)
Description
Download the LODES geographic crosswalk for one or more
states. The crosswalk maps Census block GEOIDs to higher-level
geographies and is useful for custom aggregations outside the built-in
agg_geo argument in grab_lodes().
Usage
grab_crosswalk(
state,
version = c("LODES8", "LODES7", "LODES5"),
download_dir = normalizePath(file.path(tools::R_user_dir("lehdr", which = "cache")),
mustWork = FALSE)
)
Arguments
state |
US state abbreviation in lower case. Can be a vector of
state abbreviations, e.g. |
version |
The LODES version whose crosswalk to download. Must be
one of |
download_dir |
Directory where the crosswalk file will be downloaded.
Defaults to the user-level cache directory for |
Value
A tibble containing the geographic crosswalk at the Census block level, with columns linking blocks to block groups, tracts, counties, and states.
Examples
## Not run:
# Download crosswalk for Vermont
vt_xwalk <- grab_crosswalk("vt")
# Download crosswalk for several small states
small_xwalk <- grab_crosswalk(c("wy", "nd", "sd"))
# Download a LODES7 crosswalk (2010 Census block vintage)
vt_xwalk_7 <- grab_crosswalk("vt", version = "LODES7")
## End(Not run)
Download and load LODES data into a data frame (tibble)
Description
Download LODES OD, RAC, and WAC tables from the LEHD FTP server and return a tidy data frame.
Usage
grab_lodes(
state,
year,
version = c("LODES8", "LODES7", "LODES5"),
lodes_type = c("od", "rac", "wac"),
job_type = c("JT00", "JT01", "JT02", "JT03", "JT04", "JT05"),
segment = c("S000", "SA01", "SA02", "SA03", "SE01", "SE02", "SE03", "SI01", "SI02",
"SI03"),
agg_geo = c("block", "bg", "tract", "county", "state"),
state_part = c("", "main", "aux"),
download_dir = normalizePath(file.path(tools::R_user_dir("lehdr", which = "cache")),
mustWork = FALSE),
geometry = FALSE,
use_cache = getOption("lehdr_use_cache", FALSE),
...
)
Arguments
state |
US state abbreviation in lower case, as character.
Can be a vector of states, like |
year |
Year of the LODES data, as a numeric integer.
Can be a vector of years, like |
version |
The LODES version to use. |
lodes_type |
The LODES table type. Values can be the default
origin-destination ( |
job_type |
Job type segment: |
segment |
Workforce segment. |
agg_geo |
Aggregate to a geography other than Census Block (default).
Values can be |
state_part |
Part of the state file; required when
|
download_dir |
Directory where the LODES file will be downloaded.
Defaults to the user-level cache directory for |
geometry |
If |
use_cache |
Boolean. If |
... |
Additional arguments passed to |
Value
A tibble of LODES data aggregated to block, block group, tract,
county, or state level. If geometry = TRUE and lodes_type is
"rac" or "wac", returns an sf object.
Examples
## Not run:
# Download 2014 block-level OD data for Vermont
blk_od <- grab_lodes(
state = "vt", year = 2014,
lodes_type = "od", job_type = "JT01",
segment = "SA01", state_part = "main"
)
# Download 2014 OD data for Vermont aggregated to tract level
trt_od <- grab_lodes(
state = "vt", year = 2014,
lodes_type = "od", job_type = "JT01",
segment = "SA01", state_part = "main",
agg_geo = "tract"
)
# Download 2020 RAC data for Vermont aggregated to tract level
trt_rac <- grab_lodes(
state = "vt", year = 2020,
lodes_type = "rac", job_type = "JT01",
segment = "SA01", agg_geo = "tract"
)
# Download 2020 WAC data for Vermont aggregated to tract level
trt_wac <- grab_lodes(
state = "vt", year = 2020,
lodes_type = "wac", job_type = "JT01",
segment = "SA01", agg_geo = "tract"
)
## End(Not run)