lehdr (pronounced: lee dur like a metric litre) is an R package that allows users to interface with the Longitudinal Employer-Household Dynamics (LEHD) Origin-Destination Employment Statistics (LODES) dataset, returned as tidy data frames. The package is designed to download LODES flat files (origin-destination, workplace area characteristics, and residential area characteristics), aggregate them to common Census geographies, and now includes built-in analytical functions for commute flow statistics, longitudinal job change, and earnings tier shares.
Full documentation and the Getting Started vignette are available at the lehdr pkgdown site. For a detailed walkthrough of all analytical functions and maps, see the Getting Started vignette.
You can install the released version of lehdr from CRAN with:
install.packages("lehdr")And the development version from GitHub with:
# install.packages("pak")
pak::pak("jamgreen/lehdr")Load the library and optionally set the lehdr_use_cache option to save
downloaded files for reuse across sessions:
library(lehdr)
options(lehdr_use_cache = TRUE)The grab_lodes() function downloads data for a specific state, year,
and LODES version. The table type is set with lodes_type:
origin-destination ("od"), residential area characteristics ("rac"),
or workplace area characteristics ("wac").
For example, Oregon (state = "or") for 2020 (year = 2020) from LODES
version 8 (version = "LODES8", the default), origin-destination
(lodes_type = "od"), primary jobs (job_type = "JT01", the default),
all worker segments (segment = "S000", the default), aggregated to the
Census tract level (agg_geo = "tract"):
or_od <- grab_lodes(
state = "or",
year = 2020,
version = "LODES8",
lodes_type = "od",
job_type = "JT01",
segment = "S000",
state_part = "main",
agg_geo = "tract"
)
head(or_od)Pass character vectors to state and numeric vectors to year to
retrieve multiple states and years in a single call:
or_ri_od <- grab_lodes(
state = c("or", "ri"),
year = c(2013, 2014),
lodes_type = "od",
job_type = "JT01",
segment = "S000",
state_part = "main",
agg_geo = "tract"
)
head(or_ri_od)Not all years are available for each state. For the full availability matrix, see the LEHD Technical Document at https://lehd.ces.census.gov/data/lodes/LODES8/.
Set geometry = TRUE to join Census geometries via the tigris
package. When lodes_type = "rac" or "wac", grab_lodes() returns an
sf data frame directly:
ri_rac_geo <- grab_lodes(
state = "ri",
year = 2020,
lodes_type = "rac",
agg_geo = "county",
geometry = TRUE
)
plot(ri_rac_geo["C000"])For lodes_type = "od", separate h_geometry and w_geometry columns
are returned. These can be combined into flow lines:
or_od_geo <- grab_lodes(
state = "or",
year = 2020,
lodes_type = "od",
agg_geo = "county",
geometry = TRUE,
state_part = "main"
)
h_to_w_geometry <- lapply(
seq(nrow(or_od_geo)),
function(i) {
sf::st_linestring(
c(
sf::st_centroid(or_od_geo[["h_geometry"]][[i]]),
sf::st_centroid(or_od_geo[["w_geometry"]][[i]])
)
)
}
)
h_to_w_lines <- sf::st_as_sfc(h_to_w_geometry, crs = 4269)
or_od_lines <- sf::st_set_geometry(
or_od_geo[, c("w_county", "h_county", "h_geometry", "S000")],
h_to_w_lines
)
multnomah_od_lines <- dplyr::filter(or_od_lines, w_county == "41051")
plot(multnomah_od_lines["S000"], reset = FALSE)
plot(or_od_geo["h_geometry"], lwd = 0.25, add = TRUE)The optional version parameter selects the LODES vintage. LODES8
(default) uses 2020 Census blocks. LODES7 uses 2010 Census blocks and
ends in 2019. LODES5 uses 2000 Census blocks and ends in 2009.
lehdr includes three functions for common LODES analyses.
compute_commute_stats() takes an OD data frame and returns
per-geography inflow, outflow, internal flow, net flow, and
self-containment ratio. Self-containment is the share of employed
residents who also work within the same geographic unit.
od_md <- grab_lodes(
state = "md",
year = 2019,
lodes_type = "od",
job_type = "JT00",
segment = "S000",
state_part = "main",
agg_geo = "county"
)
commute_md <- compute_commute_stats(od_md, agg_geo = "county")
commute_md |>
dplyr::arrange(dplyr::desc(self_containment)) |>
dplyr::select(county, workers_in, workers_out, net_flow, self_containment) |>
head(10)The map below shows self-containment at the Census tract level for Baltimore City, Maryland (FIPS 24510):
compute_lodes_change() computes absolute and percentage change in any
LODES variable between two years. Output can be wide (one row per
geography) or long (suitable for ggplot2).
wac_md_panel <- grab_lodes(
state = "md",
year = c(2010, 2019),
lodes_type = "wac",
job_type = "JT00",
segment = "S000",
agg_geo = "county"
)
change_md <- compute_lodes_change(
wac_md_panel,
geo_col = "w_county",
base_year = 2010,
compare_year = 2019,
variables = c("C000", "CE01", "CE02", "CE03")
)
change_md |>
dplyr::arrange(dplyr::desc(C000_change)) |>
dplyr::select(w_county, C000_base, C000_compare, C000_change, C000_pct_change) |>
head(10)The map below shows percent change in total jobs across Maryland counties from 2010 to 2019:
compute_earnings_share() computes the distribution of jobs across
LODES earnings tiers: low (up to $1,250/month), mid
($1,251-$3,333/month), and high (above $3,333/month). Use
output = "long" for a ggplot2-ready format.
wac_md <- grab_lodes(
state = "md",
year = 2019,
lodes_type = "wac",
job_type = "JT00",
segment = "S000",
agg_geo = "county"
)
earn_shares <- compute_earnings_share(wac_md, type = "wac", geo_col = "w_county")
earn_shares |>
dplyr::arrange(dplyr::desc(share_low)) |>
dplyr::select(w_county, share_low, share_mid, share_high) |>
head(10)The figures above were produced with ggplot2 and tigris. The general
pattern is: download with grab_lodes(), compute a derived variable,
fetch geometries with tigris::tracts() or tigris::counties(), join
on GEOID, and plot with geom_sf(). See vignette("getting_started")
for full figure code.
The map below shows a flow-weighted job accessibility index for Baltimore City tracts, computed directly from LODES OD data:
All figures can be reproduced by running
source("data-raw/render_vignette_figures.R") locally. The map below
shows self-containment at the Census tract level for Baltimore City,
Maryland — a simple but powerful use of LODES OD data to understand
which neighborhoods have strong local job access versus heavy
out-commuting:
See vignette("getting_started") for the full figure code and
additional maps of Maryland county job change, earnings tier
composition, and tract-level job accessibility.
Downloaded files are deleted after reading by default. Set
use_cache = TRUE in grab_lodes() or
options(lehdr_use_cache = TRUE) globally to retain files in the user
cache directory (tools::R_user_dir("lehdr", "cache")). Cache filenames
include the LODES version (e.g., lodes8_md_wac_S000_JT00_2019.csv.gz),
so switching between versions will not serve stale data from a different
vintage.
Upgrading from lehdr < 1.2.0? Earlier versions cached files without
a version prefix (e.g., md_wac_S000_JT00_2019.csv.gz). Those files
will never be matched by the new naming scheme and can be safely
deleted. To clear the entire cache:
cache_dir <- tools::R_user_dir("lehdr", "cache")
list.files(cache_dir) # inspect before deleting
unlink(cache_dir, recursive = TRUE)The LODES dataset is frequently used by transportation and economic development planners, regional economists, disaster managers, and other public servants who need fine-grained understanding of the spatial distribution of employment. Such data underpins regional travel demand models, workforce and industrial policy analysis, and, as a Census product, can be joined to Decennial or American Community Survey data to illuminate the relationship between population and employment geography.
LODES is the only source of detailed geographic information on employment for the entire country, and lehdr is designed to make it more accessible for researchers and analysts working on regional development issues.
If you use lehdr in published work, please cite it:
citation("lehdr")Green, Jamaal, Liming Wang, and Dillon Mahmoudi. 2025. “lehdr: Grab Longitudinal Employer-Household Dynamics (LEHD) Flat Files.” R package version 1.2.0. https://github.com/jamgreen/lehdr/
This package was developed by Jamaal Green, University of Pennsylvania; Dillon Mahmoudi, University of Maryland Baltimore County; and Liming Wang, Portland State University.
This package would not exist in its current format without the inspiration of Bob Rudis’s lodes package.



