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.