Energy underpins both the economic strength and the national security
of the United States.
This report examines how state-level patterns of energy
production and dependency reveal regional strengths and
vulnerabilities, and what those patterns imply for U.S. energy
security.
The analysis focuses on three core ideas:
The central research question is:
How do state-level energy production patterns reflect regional strengths and vulnerabilities, and what are the implications for U.S. energy security?
To answer this, I build an interactive choropleth map that visualizes state-level energy dependency and provides callouts for each state with production, consumption, dependency, and fuel mix information. I exclude Alaska and Hawaii from the map to keep the lower 48 states on a single, readable view.
The analysis uses the State Energy Data System (SEDS) from the U.S. Energy Information Administration. The data are pulled from EIA’s bulk CSV download.
Key series (MSN codes):
TEPRB - Total primary energy production, billion
BtuTEACB - Total primary energy consumption, billion
BtuCLPRB - Coal production, billion BtuPAPRB - Crude oil production, billion BtuNGMPB - Natural gas, marketed production, billion
BtuNUETB - Nuclear electric power, billion BtuREPRB - Renewable energy production, billion Btuprod_url <- "https://www.eia.gov/state/seds/CDF/Complete_SEDS.csv"
codes_url <- "https://www.eia.gov/state/seds/CDF/Codes_and_Descriptions.csv"
seds <- read_csv(prod_url, show_col_types = FALSE)
codes <- read_csv(codes_url, show_col_types = FALSE)
# Lookup for state codes and names
state_lookup <- tibble(
StateCode = state.abb,
state_name = state.name
)
# Latest year available in the dataset
latest_year <- max(seds$Year, na.rm = TRUE)
latest_year
## [1] 2023
needed_msns <- c("TEPRB", "TEACB", "CLPRB", "PAPRB", "NGMPB", "NUETB", "REPRB")
energy_raw <- seds %>%
filter(
MSN %in% needed_msns,
Year == latest_year,
StateCode %in% state_lookup$StateCode
) %>%
select(StateCode, MSN, Data) %>%
pivot_wider(names_from = MSN, values_from = Data) %>%
left_join(state_lookup, by = "StateCode") %>%
relocate(state_name, .before = StateCode)
head(energy_raw)
## # A tibble: 6 × 9
## state_name StateCode CLPRB NGMPB NUETB PAPRB REPRB TEACB TEPRB
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Alaska AK 15496 410727 0 884440 10087 203538 1320750
## 2 Alabama AL 303503 92525 476392 20429 210398 543739 1103247
## 3 Arkansas AR 0 399132 156492 25316 90359 287260 671299
## 4 Arizona AZ 0 30 329474 40 81595 557787 411139
## 5 California CA 0 148926 185192 673157 634319 3035725 1641594
## 6 Colorado CO 256169 2245754 0 948868 108520 446912 3559311
I define energy dependency as:
\[ \text{Dependency} = \frac{\text{Consumption} - \text{Production}}{\text{Consumption}} \]
Fuel shares are defined as the fraction of total production from each major source.
energy_state <- energy_raw %>%
mutate(
production = TEPRB,
consumption = TEACB,
dependency = ifelse(consumption > 0,
(consumption - production) / consumption,
NA_real_),
coal_share = CLPRB / production,
oil_share = PAPRB / production,
gas_share = NGMPB / production,
nuclear_share = NUETB / production,
renew_share = REPRB / production
) %>%
# Replace non-finite shares (e.g., division by zero) with 0
mutate(across(ends_with("share"), ~ ifelse(is.finite(.), ., 0)))
summary(select(energy_state, production, consumption, dependency))
## production consumption dependency
## Min. : 3315 Min. : 42621 Min. :-53.65914
## 1st Qu.: 221758 1st Qu.: 200132 1st Qu.: -1.83255
## Median : 597284 Median : 433372 Median : -0.02221
## Mean : 1957534 Mean : 560132 Mean : -4.03136
## 3rd Qu.: 1266374 3rd Qu.: 667893 3rd Qu.: 0.44438
## Max. :27104730 Max. :3323908 Max. : 0.95890
# Net exporters (lowest dependency)
exporters <- energy_state %>%
filter(!is.na(dependency)) %>%
arrange(dependency) %>%
slice_head(n = 8) %>%
mutate(state_name = fct_reorder(state_name, dependency))
# Most import-dependent (highest dependency)
importers <- energy_state %>%
filter(!is.na(dependency)) %>%
arrange(desc(dependency)) %>%
slice_head(n = 8) %>%
mutate(state_name = fct_reorder(state_name, dependency))
p1 <- ggplot(exporters, aes(x = state_name, y = dependency)) +
geom_col() +
coord_flip() +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(
title = "Top Net Energy Exporters",
x = "",
y = "Dependency (negative = exporter)"
) +
theme_minimal()
p2 <- ggplot(importers, aes(x = state_name, y = dependency)) +
geom_col() +
coord_flip() +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(
title = "Most Import-Dependent States",
x = "",
y = "Dependency (positive = importer)"
) +
theme_minimal()
p1
p2
These bar charts provide an initial view of which states are structural exporters and which are structurally dependent on imports, but they do not yet show a full geographic picture or fuel mix.
The choropleth uses lower 48 states only for a clean, contiguous map.
# Base map polygons
us_map <- maps::map("state", plot = FALSE, fill = TRUE)
us_sf <- st_as_sf(us_map) %>%
rename(geometry = geom) %>%
mutate(
state_lower = tolower(ID),
state_name_map = tools::toTitleCase(state_lower)
)
# Matching table: state.name -> lowercase
match_tbl <- tibble(
state_name = state.name,
state_lower = tolower(state.name)
)
# Attach dependency and mix to state names, exclude Alaska & Hawaii
map_data <- energy_state %>%
filter(!state_name %in% c("Alaska", "Hawaii")) %>%
left_join(match_tbl, by = "state_name") %>%
filter(!is.na(state_lower))
# Join to sf polygons
map_sf <- us_sf %>%
left_join(map_data, by = "state_lower")
# Quick check
map_sf %>%
st_drop_geometry() %>%
select(state_name_map, state_name, production, consumption, dependency) %>%
head()
## state_name_map state_name production consumption dependency
## 1 Alabama Alabama 1103247 543739 -1.0290010
## 2 Arizona Arizona 411139 557787 0.2629104
## 3 Arkansas Arkansas 671299 287260 -1.3369039
## 4 California California 1641594 3035725 0.4592415
## 5 Colorado Colorado 3559311 446912 -6.9642323
## 6 Connecticut Connecticut 177908 218868 0.1871448
The static map is suitable for inclusion as a screenshot in the PDF submission.
ggplot(map_sf) +
geom_sf(aes(fill = dependency), color = "white", size = 0.2) +
scale_fill_gradient2(
low = "blue",
mid = "white",
high = "red",
midpoint = 0,
labels = percent_format(accuracy = 1),
name = "Energy\nDependency"
) +
labs(
title = "State Energy Dependency - Lower 48 States",
subtitle = paste("Dependency = (Consumption - Production) / Consumption, Year", latest_year)
) +
theme_minimal()
The interactive map uses Leaflet. Each state includes a callout with:
To avoid leaflet legend and type errors, I clean the data, remove
NA dependencies, and ensure dependency is
numeric.
# Clean data for leaflet
map_sf_clean <- map_sf %>%
filter(!is.na(dependency)) %>%
mutate(
dependency = as.numeric(dependency),
production = as.numeric(production),
consumption = as.numeric(consumption),
coal_share = as.numeric(coal_share),
gas_share = as.numeric(gas_share),
renew_share = as.numeric(renew_share)
)
# Color palette: diverging blue-white-red with 0 as midpoint
pal <- colorNumeric(
palette = "RdBu",
domain = map_sf_clean$dependency,
reverse = TRUE,
na.color = "#f0f0f0"
)
# HTML labels (callouts)
labels <- sprintf(
"<strong>%s</strong><br/>
Production: %s billion Btu<br/>
Consumption: %s billion Btu<br/>
Dependency: %0.1f%%<br/>
Coal share: %0.1f%%<br/>
Natural gas share: %0.1f%%<br/>
Renewables share: %0.1f%%",
map_sf_clean$state_name,
comma(round(map_sf_clean$production, 0)),
comma(round(map_sf_clean$consumption, 0)),
100 * map_sf_clean$dependency,
100 * map_sf_clean$coal_share,
100 * map_sf_clean$gas_share,
100 * map_sf_clean$renew_share
) %>% lapply(htmltools::HTML)
leaflet(map_sf_clean) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(
fillColor = ~pal(dependency),
fillOpacity = 0.8,
color = "white",
weight = 1,
label = labels,
highlightOptions = highlightOptions(
weight = 2,
color = "black",
bringToFront = TRUE
)
) %>%
addLegend(
pal = pal,
values = map_sf_clean$dependency,
title = "Energy Dependency",
labFormat = labelFormat(suffix = ""),
opacity = 0.9
)
When knitting to HTML, this chunk produces the interactive map. For the PDF submission, a screenshot of either the static map or the interactive map can be captured and inserted.
To better understand why some states are exporters or import-dependent, I compare the production mix for a few illustrative states:
selected_states <- c("TX", "WY", "ND", "CA", "NY", "FL")
mix_long <- energy_state %>%
filter(StateCode %in% selected_states) %>%
select(
state_name, StateCode,
coal_share, oil_share, gas_share, nuclear_share, renew_share
) %>%
pivot_longer(
cols = ends_with("share"),
names_to = "source",
values_to = "share"
) %>%
mutate(
source = case_when(
source == "coal_share" ~ "Coal",
source == "oil_share" ~ "Oil",
source == "gas_share" ~ "Natural gas",
source == "nuclear_share" ~ "Nuclear",
source == "renew_share" ~ "Renewables",
TRUE ~ source
),
source = factor(
source,
levels = c("Coal", "Oil", "Natural gas", "Nuclear", "Renewables")
)
)
ggplot(mix_long, aes(x = state_name, y = share, fill = source)) +
geom_col(width = 0.7) +
scale_y_continuous(labels = percent_format(accuracy = 1)) +
labs(
title = "Energy Production Mix for Selected States",
subtitle = paste("Shares of total primary energy production,", latest_year),
x = "",
y = "Share of total production",
fill = "Energy source"
) +
theme_minimal()
This comparison helps link dependency status to the underlying fuel portfolios, separating states that export fossil fuels from those that depend more heavily on imported fuels or electricity.
Regional patterns and dependencies
The choropleth map highlights a clear regional divide in U.S. energy production and dependency. A handful of resource-rich states in the interior and Gulf regions-such as Texas, Wyoming, North Dakota, and New Mexico-produce far more energy than they consume, making them consistent net exporters. Many states along the East and West Coasts, including California, New York, and Florida, show positive dependency values, indicating that they rely heavily on energy generated elsewhere. The lower 48 view also reveals clusters of relatively balanced states in parts of the Midwest and Northwest, where in-state production and consumption are closer in scale. Overall, the map shows that national energy security is supported by a limited set of exporting states that underpin supply for multiple import-dependent regions.
Implications for U.S. energy security and policy
These patterns have direct implications for U.S. energy security and long-term policy design. States with high import dependency are more exposed to supply disruptions, transmission bottlenecks, and price volatility because they rely on interstate pipelines, transmission lines, and imported fuels. At the same time, major producing states carry a disproportionate responsibility for maintaining stable output and infrastructure, making them critical nodes in the national energy system. Policymakers can use these insights to prioritize investments in grid resilience, diversify the fuel mix of highly dependent states, and encourage more in-state renewable production where feasible. Strengthening regional interconnections while reducing extreme dependency levels can help create a more balanced and resilient U.S. energy landscape.