Introduction

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:

  • Total energy production by state - which states act as energy “anchors” for the country.
  • Energy mix by fuel type - coal, oil, natural gas, nuclear, and renewables.
  • Energy dependency - how much a state relies on energy produced elsewhere.

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.

Data Collection

Source: EIA State Energy Data System (SEDS)

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 Btu
  • TEACB - Total primary energy consumption, billion Btu
  • CLPRB - Coal production, billion Btu
  • PAPRB - Crude oil production, billion Btu
  • NGMPB - Natural gas, marketed production, billion Btu
  • NUETB - Nuclear electric power, billion Btu
  • REPRB - Renewable energy production, billion Btu
prod_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

Filter to production, consumption, and fuel-specific series

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

Energy Production, Consumption, and Dependency

Define dependency and fuel mix

I define energy dependency as:

\[ \text{Dependency} = \frac{\text{Consumption} - \text{Production}}{\text{Consumption}} \]

  • Dependency > 0 → net importer (relies on external sources).
  • Dependency < 0 → net exporter (produces more than is consumed in-state).

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

Top net exporters and import-dependent states

# 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.

Choropleth Map Design

Build spatial data for the lower 48 states

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

Static choropleth: energy dependency

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()

  • Blue states have negative dependency (they are net exporters).
  • Red states have positive dependency (they are net importers).
  • States close to white are roughly balanced between in-state production and consumption.

Interactive Choropleth Map with Callouts

The interactive map uses Leaflet. Each state includes a callout with:

  • Total production and consumption (billion Btu)
  • Dependency (%)
  • Shares of coal, natural gas, and renewables in production

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.

Fuel Mix Comparison for Selected States

To better understand why some states are exporters or import-dependent, I compare the production mix for a few illustrative states:

  • Major exporters: Texas (TX), Wyoming (WY), North Dakota (ND)
  • High-dependency states: California (CA), New York (NY), Florida (FL)
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.

Written Overview

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.