Part I: Introduction¶
Electric vehicles (EVs) are reshaping long‑distance travel in the United States, yet the charging network that supports them remains uneven and often difficult to navigate. For extended travel, effective route planning is essential to avoid delays, requiring attention to the spatial distribution of charging stations as well as charger compatibility and charging speed. According to Varga et al. (2019), driving range continues to be the primary factor influencing consumers’ decisions to adopt electric vehicles, making it essential to assess whether the existing charging infrastructure actually enables drivers to use that range effectively on long‑distance routes. This project evaluates how well EV drivers can road‑trip across the country by mapping charging station coverage along interstate highways, identifying where chargers are reliably spaced, where major gaps exist, and how these gaps align with real travel demand.
We integrate two national datasets: EV charging station data and highway mobility‑flow data. Chargers are spatially linked to the nearest interstate nodes to evaluate road‑trip‑relevant accessibility, and a customized priority score is used to identify “EV charging deserts”, defined as highway segments where no Level 2 or DC Fast chargers are reachable within a reasonable detour. We then proposes potential locations for expanding the charging network based on the spatial distribution of existing infrastructure. The resulting insights are valuable for firms seeking to identify strategic investment locations. The final deliverable is a list of high‑priority charging gaps along U.S. interstates, supported by national and corridor‑level maps. By revealing where heavy travel demand meets limited charging access, this project highlights the most critical barriers to seamless electric road‑tripping.
Part II: Method¶
Preliminary Analysis
We began with a preliminary exploratory analysis (Part III) to understand broad patterns of EV chargers and the U.S. interstate system. We mapped all public chargers located within five miles of the interstate system and visualized their 25‑mile service areas, overlaid with interstate traffic volumes measured using Average Annual Daily Traffic (AADT). This initial visualization highlighted where high‑demand corridors lacked adequate charging coverage and helped validate the relevance of our data for subsequent modeling.
Main Analysis & Visualization
Our analysis (Part IV) proceeds in two stages. First, we develop a national‑scale scoring system that identifies EV‑charging gaps along U.S. interstates by combining 2 factors: vehicle miles traveled (VMT) and distance to the nearest charger. After cleaning and standardizing the data, we compute a preliminary priority score defined as the product of VMT and charger distance. This score highlights locations where high travel demand intersects with limited charging availability. A list of top 10 highest priority ZIP code area is generated and visualized as results. The resulting spatial patterns provide a broad understanding of where charging gaps are most consequential at the national level and establish a baseline for more detailed regional analysis.
In the second stage, we refine this approach by incorporating network analysis within a metropolitan case study of the Twin Cities. Using OSMnx and NetworkX, we extract all motorway and motorway‑link segments within a 20‑km radius of Minneapolis–St. Paul and construct a directed, travel‑time‑weighted graph. We then compute betweenness centrality for both nodes and edges using NetworkX, quantifying how frequently each segment lies on shortest paths throughout the network. These centrality values identify critical connectors and potential chokepoints that are not captured by VMT or charger distance alone. The network‑derived edge centrality values are exported and spatially merged with Minnesota’s interstate dataset, which contains VMT and charger‑distance attributes. After simplifying geometries, aligning coordinate reference systems, and performing a nearest‑segment spatial join, each Twin Cities road segment inherits the appropriate VMT and charger‑distance values. We then compute an enhanced priority metric defined as: $$\text{Score} = \text{VMT} \cdot \text{distance to nearest charger} \cdot \text{Betweeness Centrality}$$ This metric identifies segments where high traffic volumes, poor charging access, and structural network importance converge.
To communicate the results of our analysis, we generate a series of maps that translate the combined metric into an interpretable spatial form. Highway segments are visualized using a log‑scaled color gradient, allowing large differences in VMT, charger distance, and betweenness centrality to be displayed without overwhelming the map. Darker tones indicate segments with higher priority scores, while lighter tones represent lower‑priority areas. A contextual basemap provides geographic reference, and the highest‑scoring segments are highlighted to clearly identify locations where new EV‑charging infrastructure would have the greatest impact.
Part III: Data Processing & Preliminary Analysis¶
Data Background & Selection¶
We will cross analyze two open source datasets:
- EV Charging Stations database:
The U.S. Department of Energy’s Alternative Fuels Data Center (AFDC) provides the national database of public EV charging stations. Each record includes station location, access type, charging level, connector type, and operational status. For this project, we filter stations to reflect non‑commercial, long‑distance personal travel.
Filters applied:
- ```Region - United States```
- ```Car Class Type - Class 1 & Class 2```: These two classes reflect light-duty vehicles. Class 1 includes passenger cars, minivans, SUVs, and small pickup trucks, while Class 2 includes standard-size pickup trucks and camper vans.
- ```Charger Type - Level 2 & DC Fast```: Level 2 adds 15–40 miles per hour and is common for commutes, and DC Fast Chargers provide 100-300+ miles in 30–60 minutes, best for road trips. Level 1 is mainly for overnight at-home charging; we will thus focus on Level 2 and DC Fast chargers.
- ```Connector Type - CCS (DC), J1772 (AC), NACS(J3400 AC/DC)```:
- **CCS (Combined Charging System)**: the most common DC connector for non‑Tesla EVs, used by most non‑Tesla EVs sold before 2025 for DC Fast charging.
- **J1772**: the universal AC connector for non‑Tesla EVs, used by all non‑Tesla EVs for Level 2 charging. This represents the majority of workplace, apartment, and public slow‑charging infrastructure.
- **NACS (North American Charging Standard)**: the new dominant standard, now adopted by nearly every major automaker for North America starting 2025–2026. Backed by Tesla’s Supercharger network, which is the largest and most reliable fast‑charging network in the U.S.
- National Highway Traffic Mobility‑flow data:
The U.S. Department of Transportation's public data portal provides data on national mobility‑flow, including attributes such as roadway geometry and traffic demand metrics for U.S. highways. Key attributes include route identifiers, begin/end points, segment length, functional classification, and traffic volumes such as AADT (Annual Average Daily Traffic) and truck AADT. These fields capture how heavily each segment is used and allow us to weight EV charging gaps by real travel demand. This dataset is essential for distinguishing minor gaps from those that meaningfully affect long‑distance mobility. To reflect non-commercial roadtrip car types, we will be using AADT to quantify mobility flow.
Data Download & Cleaning¶
import pandas as pd
import geopandas as gpd
import dask_geopandas as dgpd
import matplotlib.pyplot as plt
import osmnx as ox
import networkx as nx
import shapely
import contextily as ctx
import numpy as np
from matplotlib.colors import LogNorm
ox.settings.use_cache = True
# create bounding box and constant variables
# Isolate only US States, excluding Hawaii and Alaska
USA_48_STATES = {
"min_long": -128.320313,
"max_long": -65.039063,
"min_lat": 24.367114,
"max_lat": 50.401515
}
USA_48_STATES_BBOX = (USA_48_STATES["min_long"], USA_48_STATES["min_lat"], USA_48_STATES["max_long"], USA_48_STATES["max_lat"])
ONE_MILE_IN_METERS = 1609.344
# load charger location
us_charger_locations = pd.read_csv('data/USChargingLocations.csv')
us_charger_locations = gpd.GeoDataFrame(us_charger_locations,
geometry = gpd.points_from_xy(
us_charger_locations['Longitude'],
us_charger_locations['Latitude']))
# filters charging locations to 48 states
us_charger_locations = us_charger_locations.cx[USA_48_STATES["min_long"] : USA_48_STATES["max_long"],
USA_48_STATES["min_lat"] : USA_48_STATES["max_lat"]]
us_charger_locations = us_charger_locations.set_crs('EPSG:4326')
C:\Users\May\AppData\Local\Temp\ipykernel_3152\1231135308.py:2: DtypeWarning: Columns (20,40,64,69) have mixed types. Specify dtype option on import or set low_memory=False.
us_charger_locations = pd.read_csv('data/USChargingLocations.csv')
# load interstate data
# big file, took a while to load
interstates = gpd.read_file('data/spatial_interstates_w_mobility.geojson', bbox = USA_48_STATES_BBOX)
# this dataframe has almost 100 columns, so we are narrowing just to the important columns
interstates = interstates[[':id', 'aadt', 'sectionlength', 'geometry']]
# convert both to correct types
interstates.loc[:, 'sectionlength'] = interstates['sectionlength'].astype('float')
interstates.loc[:, 'aadt'] = interstates['aadt'].astype('float')
# makes calculations faster to simplify geometry/lines for processing. doesnt affect viewing from a national level
interstates = interstates.to_crs('EPSG:9311')
interstates.loc[:, 'geometry'] = interstates.simplify(50)
interstates = interstates[interstates.is_valid & ~interstates.is_empty]
# plot both together, also takes a while
us_charger_locations = us_charger_locations.to_crs(interstates.crs)
ax = interstates.plot(color='grey')
us_charger_locations.plot(ax = ax, color='red', markersize=0.5)
ax.set_title("EV Charger Locations vs Interstate Network", fontsize=15, pad=10)
ax.set_axis_off()
Preliminary Analysis & Visualization¶
To explore the data, we generate initial visualizations that reveal key spatial relationships across datasets and help assess how well the underlying patterns align with the goals of our project. This establish the foundation for subsequent analysis and visualization.
We construct a national‑scale map of EV charging accessibility by identifying all chargers located within five mile of the interstate network and visualizing their corresponding 25‑mile service areas. We overlay interstate traffic volumes using Average Annual Daily Traffic (AADT) as mobility metric to highlight where high‑demand corridors lack adequate charging coverage. The resulting color‑graded map uses darker tones to represent heavier traffic flows and lighter tones to indicate lower‑volume segments, making charging deserts along major U.S. corridors immediately visible and interpretable.
Buffer Distance¶
Buffer distance was chosen according to the 2025 National Electric Vehicle Infrastructure (NEVI) guidelines (Federal Highway Administration, 2025) and the context of road tripping. According to the 2025 NEVI guidelines, states have broad flexibility to determine fast charging station spacing along Alternative Fuel Corridors, adjusting intervals based on geography, traffic patterns, grid capacity, and regional EV adoption. FHWA treats approximately 50 miles as a recommended benchmark for maintaining corridor continuity and reducing the likelihood of charging deserts, but it is no longer a prescriptive requirement. The minimum technical standards such as four 150 kW ports per site, uptime requirements, and open access payment systems remain in effect, preserving consistency across the national network. As a result, current planning practices emphasize corridor spacing in the range of 50–80 km (30–50 miles) on major highways, with denser deployment in urban and commuter regions and more tailored strategies for rural and remote areas. Thus, we chose a 25‑mile radius buffer around each charger to ensure no two stations were more than 50 miles apart. Under the context of roadtripping, we want to make sure chargers are near the interstate. Since EVs can sometimes take hours to charge, we don't want to add another hour of driving just to get to a charger. Hence the 5-mile buffer on each side of the interstate.
# Buffering the interstate network by 5 mile to find chargers near interstates
interstates_5_miles = interstates.to_crs('EPSG:9311').buffer(ONE_MILE_IN_METERS * 5)
# Spatially joining chargers to those buffers to keep only chargers within 5 miles of an interstate
charging_locations_by_interstate = gpd.sjoin(
us_charger_locations.to_crs('EPSG:9311'),
gpd.GeoDataFrame(geometry=interstates_5_miles),
how="inner",
predicate="intersects"
).drop_duplicates(subset='ID')
# simplifying the interstate geometries for faster plotting
interstates_simple = interstates.to_crs('EPSG:9311')
interstates_simple['geometry'] = interstates_simple.simplify(500)
interstates_simple = interstates_simple[interstates_simple.is_valid & ~interstates_simple.is_empty]
# fig 2: AADT mobility flow roadmap
fig, ax = plt.subplots(figsize=(15, 10))
# Interstates colored by AADT (traffic volume)
im = interstates_simple.plot(
ax=ax,
alpha=0.5,
column='aadt',
cmap='viridis_r',
linewidth=2,
legend=False
)
cbar = fig.colorbar(im.get_children()[0], ax=ax, orientation='vertical')
cbar.set_label("Annual Average Daily Traffic (AADT)")
ax.set_title("AADT Mobility Flow Roadmap", fontsize=20, pad=15)
ax.text(
0.5, -0.05,
"Color scale represents traffic volume",
fontsize=14,
ha='center',
va='top',
transform=ax.transAxes
)
Text(0.5, -0.05, 'Color scale represents traffic volume')
# fig.3: EV Charger Coverage and Interstate Mobility Flow
fig, ax = plt.subplots(figsize=(15, 10))
# Buffering chargers by 25 miles radius to visualize coverage zones
charger_buffers = charging_locations_by_interstate.to_crs('EPSG:9311')
charger_buffers = charger_buffers.buffer(1609.344 * 25) # 1609.344 m = 1 mi
charger_buffers = charger_buffers[charger_buffers.is_valid & ~charger_buffers.is_empty]
im = interstates_simple.plot(
ax=ax,
alpha=0.5,
column='aadt',
cmap='viridis_r',
linewidth=2,
legend=False
)
# Plotting the simplified interstates + charger coverage buffers
# Interstates colored by AADT (traffic volume)
charger_buffers.plot(ax=ax, color='red', alpha=0.35)
cbar = fig.colorbar(im.get_children()[0], ax=ax, orientation='vertical')
cbar.set_label("Annual Average Daily Traffic (AADT)", fontsize=12)
ax.set_title(
"EV Charger Coverage and Interstate Mobility Flow",
fontsize=22,
pad=18
)
ax.text(
0.5, -0.06,
"25-mile charger service areas overlaid on AADT-colored interstate network",
fontsize=14,
ha='center',
va='top',
transform=ax.transAxes
)
ax.set_axis_off()
ax.set_aspect('equal')
Findings¶
Preliminary analysis reveals a highly uneven spatial structure in the U.S. interstate network and its associated EV charging landscape. Dense clusters of nodes and connections dominates the eastern half of the country, reflecting both population concentration and the tight interstate grid. In contrast, the western states show long, sparsely connected corridors with much less nodes. This provides an immediate visual idea of where charging access is likely to be most fragile. The pattern also highlights a core structural imbalance: the places with the longest distances between interstates are also the places where charger coverage is thinnest, amplifying risks for long‑distance travel. The map also makes it clear that national connectivity relies on a small number of critical east–west and north–south corridors; gaps along these routes would disproportionately affect mobility. The AADT‑coded roadway network reinforces this pattern. Lighter, lower-traffic segments appear more on longer stretches of the West, and higher traffic areas are concentrated around eastern populated cities.
When the 25‑mile charger service‑area buffers are overlaid on this mobility landscape, the interaction between the two layers becomes clear. Because each buffer is drawn with partial transparency, overlapping service areas appear darker, meaning that deeper red zones correspond to locations where multiple chargers fall within overlapping radii. These darker regions therefore signal higher charger density and greater redundancy, often aligning with major corridors, junctions, or urban centers where mobility demand is highest. In contrast, the long, lightly traveled western corridors show both sparse interstate connectivity and minimal buffer overlap, underscoring the vulnerability of rural segments with few alternative routes.
Overall, the combined visualization clarifies where traffic intensity aligns or fails to align with existing charging coverage, highlighting the nation’s most critical charging deserts.
Part IV: Analysis & Visualization¶
Our analysis proceeds in two stages. First, we develop a national‑scale scoring system that identifies EV‑charging gaps along U.S. interstates by combining 2 factors: vehicle miles traveled (VMT) and distance to the nearest charger. This produces a broad landscape of where travel demand and sparse charging infrastructure intersect, revealing large‑scale patterns in coverage gaps across the U.S. highway system.
In the second stage, we refine this approach by incorporating network analysis within a metropolitan case study of the Twin Cities. Using OSMnx and NetworkX, we calculate edge betweenness centrality to capture how often each segment functions as a critical connector in regional mobility. Integrating these centrality values with VMT and charger‑distance data yields an enhanced priority score that highlights not only where chargers are lacking, but where new infrastructure would most improve the robustness and connectivity of the metropolitan network.
Stage 1. Identifying High‑Priority EV Charging Deserts: Creating a Priority Score System¶
In the preliminary analysis, we relied on Average Annual Daily Traffic (AADT) to visualize mobility patterns and used a 25‑mile radius buffer to approximate charger service areas. In this section, we refine our approach by developing a more robust and actionable prioritization metric for identifying EV charging deserts.
- Traffic flow: While AADT is useful for understanding how many vehicles use a highway segment, it is not sufficient for identifying EV charging deserts since it treats every segment as if it were the same length. This means a short urban connector with high traffic appears just as important as a 50‑mile rural stretch with moderate traffic. It also ignores charger accessibility entirely: a segment with high AADT but a charger located one mile away is fundamentally different from a segment with the same AADT but the nearest charger 40 miles away. Because AADT captures only traffic volume and not exposure to charging scarcity, it cannot meaningfully represent the real risk EV drivers face on long‑distance corridors. This can be resolved by normalizing AADT, known as
VMT (Vehicle Miles Traveled). $$\text{VMT} = \text{AADT} \times \text{segment length}$$ - Charger service area: A simple 25‑mile buffer around chargers provides a binary measure of coverage; segments are either “within range” or “not.” This approach masks important variation. A segment located 1 mile from a charger is treated the same as one 24.9 miles away, even though the practical accessibility difference is substantial. The buffer also ignores mobility demand: a lightly traveled rural road and a major interstate corridor receive identical treatment if they fall outside the buffer. As a result, the buffer method identifies where chargers are absent but cannot tell us where the absence matters most. Thus, we will be using
distance to nearest chargerinstead.
As a result, we create a scoring system with the combined metric of Vehicle Miles Traveled (VMT) multiplied by distance to the nearest charger. The composite score is defined as: $$ \text{Score} = \text{VMT} \times \text{distance to nearest charger} $$ This score provides a more meaningful and risk‑aligned measure of EV charging deserts, as it weights mobility demand by the severity of charger scarcity. Segments that are long, heavily traveled, and far from chargers receive the highest scores, reflecting locations where inadequate charging access would affect the greatest amount of travel.
The workflow proceeds as follow: resolving missing traffic data & computing Vehicle Miles Traveled (VMT), measuring charger distance, generating a composite priority score, and aggregating results to ZIP‑code areas.
1. Calculate VMT for each Highway Segment
# seperate segments into two dataframes: those with a value for aadt, and those without a value for aadt
has_aadt = interstates[~interstates['aadt'].isna()].copy()
no_aadt = interstates[interstates['aadt'].isna()].copy()
# pull aadt value from the closest segement with an aadt value
resolved_aadt = gpd.sjoin_nearest(
no_aadt.drop(columns='aadt'),
has_aadt[['aadt', 'geometry']],
how = 'left',
max_distance = ONE_MILE_IN_METERS * 5
)
# apply these values back to the current dataframe
interstates.loc[resolved_aadt.index, 'aadt'] = resolved_aadt['aadt']
# calculate vmt
interstates['vmt'] = interstates['aadt'] * interstates['sectionlength']
# re-enforce types
interstates[['aadt', 'sectionlength', 'vmt']] = interstates[['aadt', 'sectionlength', 'vmt']].astype(float)
2. Find closest charger
In the context of road tripping, we want to make sure chargers are near the interstate. Since EVs can sometimes take hours to charge, we don't want to add another hour of driving just to get to a charger. Because this operation is computationally intensive at national scale, we use Dask‑GeoPandas to parallelize the nearest‑neighbor search across multiple partitions. For each segment, we record the distance to the closest charger and convert this value from meters to miles.
# create 5 mile buffers
interstates_5_miles = interstates.to_crs('EPSG:9311').buffer(ONE_MILE_IN_METERS * 5)
# filters chargers to only include ones 5 miles from the interstate
charging_locations_by_interstate = gpd.sjoin(
us_charger_locations.to_crs('EPSG:9311'),
gpd.GeoDataFrame(geometry=interstates_5_miles),
how="inner",
predicate="intersects"
).drop_duplicates(subset='ID')
# create function to find distance to the nearest charger
def find_dist_to_nearest_charger(partition, points):
if partition.empty:
return partition
return gpd.sjoin_nearest(
partition,
points,
how="left",
distance_col="dist_to_charger"
)
# uses dask to make this process much faster
# number of ideal partitions depends on number of cpu cores, and may need tweaking based on where you're running this
d_interstates = dgpd.from_geopandas(interstates, npartitions=24)
joined_delayed = d_interstates.map_partitions(
find_dist_to_nearest_charger,
points=charging_locations_by_interstate[['geometry']]
)
# compute thing to find nearest charger
interstates_with_info = joined_delayed.compute(scheduler='threads')
# clean
interstates_with_info = interstates_with_info.drop_duplicates(subset=[':id'])
interstates_with_info['dist_charger_miles'] = interstates_with_info['dist_to_charger'] / ONE_MILE_IN_METERS
3. Create overall priority score to find high priority EV deserts
interstates_with_info['score'] = interstates_with_info['vmt'] * interstates_with_info['dist_charger_miles']
# keep relevant columns
interstates_with_info = interstates_with_info[[':id', 'aadt', 'sectionlength', 'vmt', 'dist_charger_miles', 'score', 'geometry']]
interstates_with_info.to_file('data/interstates_with_charger_info.geojson', driver='GeoJSON')
# fig 4: Visualization of priority score on interstate network
interstates_with_info = interstates_with_info.set_geometry("geometry")
fig, ax = plt.subplots(figsize=(14, 10))
interstates_with_info.plot(
column='score',
cmap='Reds',
linewidth=1,
legend=True,
ax=ax,
scheme='quantiles', # or 'naturalbreaks'
k=5
)
ax.set_title("U.S. Interstate by EV Charging Desert Priority Score (Segment-Level)", fontsize=18)
ax.set_axis_off()
4. Identifying recommended locations for future EV charging infrastructure
To support place‑based recommendations, we spatially join each interstate segment to its corresponding ZIP Code Tabulation Area (ZCTA). Because segments may span multiple ZIP codes, we use segment centroids to assign each segment to a single ZIP code. This allows us to aggregate segment‑level scores into ZIP‑code‑level averages. We compute the mean priority score for each ZIP code and rank them from highest to lowest. The top ten ZIP codes represent the most critical EV charging deserts, where high mobility demand intersects with poor charger accessibility. These ZIP codes form the basis for targeted recommendations for future EV charging infrastructure deployment.
# load zip code shapefile
zcta = gpd.read_file('data/zcta_shapefile/tl_2025_us_zcta520.shp')
# only keep relevant cols
zcta = zcta[['ZCTA5CE20', 'geometry']]
zcta = zcta.rename({"ZCTA5CE20": "zip_code"}, axis = 1)
# re-project to equal-area and meters, and fix typing
zcta = zcta.to_crs('EPSG:9311')
zcta.loc[:, 'zip_code'] = zcta['zip_code'].astype('int')
# To make this easier for segements between zip codes,
# we will use the centroid of each segment to find which zip code it belongs to.
interstates_with_info['centroid'] = interstates_with_info.geometry.centroid
# spatial join zip-code to each segement
interstates_with_info = gpd.sjoin(
interstates_with_info.set_geometry('centroid'),
zcta,
how = "left",
predicate = "within"
)
# for vizualization
interstates_with_info = interstates_with_info.drop('centroid', axis = 1)
interstates_with_info.to_file('data/interstates_with_charger_info.geojson', driver='GeoJSON')
# find highest priority zipcodes
high_priority_zipcodes = interstates_with_info.groupby('zip_code')['score'].mean()
top_10_deserts_zipcodes = high_priority_zipcodes.sort_values(ascending=False)[0:10].index.to_list()
top_10_deserts_zipcodes
[41098, 99356, 87120, 36613, 56389, 29377, 87943, 59435, 36109, 32033]
## fig 5: Locations of Final Recommended ZIP Codes on U.S. Interstate Network
# fix geometry
interstates_with_info = interstates_with_info.set_geometry("geometry")
# compute centroid
centroids = zcta.copy()
centroids = centroids.set_geometry(centroids.geometry.centroid)
# filter to top 10 ZIP codes
final_zip_points = centroids[centroids['zip_code'].isin(top_10_deserts_zipcodes)]
# compute centroids for all ZIP codes
zcta['centroid'] = zcta.geometry.centroid
# filter to top 10 ZIP codes
final_zip_points = zcta[zcta['zip_code'].isin(top_10_deserts_zipcodes)].set_geometry('centroid')
# plot
fig, ax = plt.subplots(figsize=(14, 10))
# base layer: interstates
interstates_with_info.plot(
ax=ax,
color='lightgrey',
linewidth=0.5,
zorder=1
)
# ZIP code points
final_zip_points.plot(
ax=ax,
color='red',
markersize=80,
zorder=3
)
ax.set_title("Locations of Final Recommended ZIP Codes on U.S. Interstate Network", fontsize=18)
ax.set_axis_off()
Stage 1 Results: Spatial Pattern Interpretation of the Top‑Ranked ZIP Codes¶
Our scoring system generated a ranked list of ZIP codes prioritized for EV‑charger deployment. The top ten recommended locations are listed below:
| ZIP Code | City / Area | State |
|---|---|---|
| 41098 | Warsaw | Kentucky |
| 99356 | White Swan | Washington |
| 87120 | Albuquerque (West Side) | New Mexico |
| 36613 | Mobile (North) | Alabama |
| 56389 | Sauk Centre / West Union | Minnesota |
| 29377 | Startex / Duncan area | South Carolina |
| 87943 | Truth or Consequences (rural area) | New Mexico |
| 59435 | Fort Benton | Montana |
| 36109 | Montgomery (East) | Alabama |
| 32033 | Elkton / Hastings area | Florida |
The ten highest‑priority ZIP codes reveal a coherent spatial pattern that reflects how EV‑charging gaps align with national travel corridors and regional infrastructure disparities. Broadly, the model highlights four types of areas:
Rural Western corridors (Montana, New Mexico, Washington): These locations fall along long, sparsely populated interstate stretches where charger spacing is wide and alternative routes are limited. Western states have large geographic distances between towns, meaning even moderate traffic volumes translate into high VMT exposure. The model flags these corridors because long‑distance travelers face the greatest risk of encountering extended charger gaps.
Southern interstate‑adjacent communities (Alabama, South Carolina, Florida): These ZIP codes sit near major interstates in the Southeast—regions with growing EV adoption but historically uneven charging investment. Traffic volumes are higher than in the rural West, but charger density remains inconsistent outside major metros. The model identifies these communities as strategic infill points where new chargers would support both local residents and interstate travelers.
Midwestern rural gaps (Minnesota): The Midwest generally has strong interstate connectivity, but rural counties often lack public charging despite steady through‑traffic. The Minnesota ZIP code in the top‑10 list represents this pattern: a low‑density area where long segments of highway have few or no chargers, creating vulnerability for regional travel and freight corridors.
Kentucky river‑corridor region: This area reflects a different structural issue: river‑adjacent towns where geography constrains road networks. Limited parallel routes mean that a single charger gap affects a disproportionately large share of travelers. The model elevates this region because its combination of moderate VMT and constrained mobility makes it a high‑impact location for new infrastructure.
Together, these clusters show that the scoring system pinpoints critical travel corridors where charger scarcity intersects with traffic volumes. These are locations where a new charger would reduce range anxiety, improve network redundancy, and strengthen long‑distance EV mobility across the national highway system.
Stage 2. Incorporating Network Analysis: Demonstration on Twin Cities, MN¶
To further refine our scoring system, we incorporate network analysis. Adding betweenness centrality into the scoring framework enhances the model’s ability to identify high‑impact locations for EV‑charger deployment because it captures a structural dimension of the road network that VMT and charger distance alone cannot. While VMT tells us how many vehicles use a segment, and distance to the nearest charger reflects how underserved that segment is, neither metric reveals how essential a road is for connecting origins and destinations across the network. Betweenness centrality fills this gap by quantifying how often a segment lies on the shortest paths between other points in the system. Segments with high betweenness act as critical connectors or chokepoints: if they lack charging infrastructure, a disproportionately large share of regional trips is affected. By integrating betweenness into the score, the model prioritizes locations where charger installation would not only serve high traffic volumes but also strengthen the resilience and redundancy of the overall mobility network. This produces a more targeted and defensible set of recommendations. The priority score is now calculated as: $$\text{Score} = \text{VMT} \cdot \text{distance to nearest charger} \cdot \text{Betweeness Centrality}$$
To streamline computation and reduce processing time, we downscale our analysis to focus on the Twin Cities region of Minnesota instead of the entire United States. This area provides a manageable yet sufficiently complex subset for demonstrating our workflow while preserving the characteristics of interstate/US highway mobility patterns. Although we present results at this regional scale, the full methodology and codebase are designed to scale to the national level and operate directly on the complete U.S. dataset we assembled.
The workflow proceeds as follow: build Twin Cities road network and add travel speeds and travel times, compute betweenness centrality and edge betweeness centrality, load and prepare interstate/highway data, calculate new score incorporating betweenness centrality.
1. Build a Twin Cities Road Network
center_point = (44.965, -93.18) # approximate center of Minneapolis-St Paul
radius_m = 20000 # 20 km radius (taking a sample of this Metro Area)
# Query for motorways and motorway links
motorway_filter = '["highway"~"motorway|motorway_link"]'
# initialize graph
G = ox.graph_from_point(
center_point,
dist=radius_m,
custom_filter=motorway_filter,
simplify=False,
retain_all=True
)
# add travel speeds and travel times
G = ox.routing.add_edge_speeds(G)
G = ox.routing.add_edge_travel_times(G)
2. Calculate betweenness centrality & edge centrality
# Calculation: betweenness centrality
D = ox.convert.to_digraph(G, weight="travel_time")
bc = nx.betweenness_centrality(
D,
k=300, # sample 300 nodes instead of full exact BC, to ease computation time
weight="travel_time",
normalized=True
)
nx.set_node_attributes(G, bc, "bc")
# fig 6: Visualization of betweenness centrality
nc = ox.plot.get_node_colors_by_attr(G, "bc", cmap="plasma")
fig, ax = ox.plot_graph(
G,
bgcolor="black",
node_color=nc,
node_size=40,
edge_color="white",
edge_linewidth=1
)
# Edge centrality: convert this graph to edge centrality
edge_centrality = nx.betweenness_centrality(nx.line_graph(G), k=500)
nx.set_edge_attributes(G, edge_centrality, "edge_centrality")
ec = ox.plot.get_edge_colors_by_attr(G, 'edge_centrality', cmap='plasma')
fig, ax = ox.plot_graph(G, edge_color=ec, edge_linewidth=2, node_size=0)
# download edges and nodes files
gdf_nodes, gdf_edges = ox.graph_to_gdfs(G)
gdf_edges.to_file("data/edges1.geojson", driver="GeoJSON")
gdf_nodes.to_file("data/nodes1.geojson", driver="GeoJSON")
3. Load and Prepare Interstate Dataset
- g1: Twin Cities OSMnx edges (with centrality)
- g2: national interstate dataset (with VMT + charger distance)
g1 = gpd.read_file("data/edges1.geojson") # Twin Cities OSMnx edges
g2 = gpd.read_file("data/interstates_with_charger_info.geojson") # National dataset
# Geometry simplification & reprojection
# Reproject g2
g2 = g2.to_crs(epsg=4326)
# Condense g2 to only include interstate highways in Minnesota
minnesota = ox.geocode_to_gdf("Minnesota")
# Merge g2 with minn_union
minn_union = minnesota.union_all()
g2_minn = g2[g2.intersects(minn_union)]
# Simplify geometry
g1.loc[:, "geom_simple"] = g1.geometry.simplify(0.00001)
g2_minn = g2_minn.copy()
g2_minn.loc[:, "geom_simple"] = g2_minn.geometry.simplify(0.00001)
# Reproject both datasets to a projected CRS
g1_proj = g1.to_crs(3071)
g2_minn_proj = g2_minn.to_crs(3071)
# Simplify geometry for faster computation time & visualization
g1_proj["geom_simple"] = g1_proj.geometry.simplify(5) #(5 meters)
g2_minn_proj["geom_simple"] = g2_minn_proj.geometry.simplify(5)
for df in [g1_proj, g2_minn_proj]:
df.drop(columns=["index_right", "index_left"], errors="ignore", inplace=True)
# Merge datasets
merged_proj = gpd.sjoin_nearest(
g1_proj.set_geometry("geom_simple"),
g2_minn_proj.set_geometry("geom_simple"),
how="left",
distance_col="match_distance"
)
merged = merged_proj.to_crs(4326)
# Ensure there is one correct geometry field
merged = merged.drop(columns=["geom_simple", "geometry_right"], errors="ignore")
[col for col in merged.columns if merged[col].dtype == "geometry"]
['geometry_left']
# Ensure geometry is set to the correct geometry column
merged = merged.set_geometry("geometry_left")
# output picture & download GeoJSON of merged datasets
merged.to_file("twincities_interstates_merged.geojson", driver="GeoJSON")
4. Attach VMT & charger distance to Twin Cities edges and calculate score
The improved priority score incorporates betweenness centrality. The score is calculated as: $$\text{Score} = \text{VMT} \cdot \text{distance to nearest charger} \cdot \text{Betweeness Centrality}$$
merged_final = gpd.read_file("twincities_interstates_merged.geojson")
# Change vmt to type float64
merged_final["vmt"] = pd.to_numeric(merged_final["vmt"], errors="coerce")
# Calculate final combined metric for new EV charging location proposal
merged_final["combined_metric"]=(
merged_final["edge_centrality"] *
merged_final["vmt"] *
merged_final["dist_charger_miles"]
)
5. Visualize
A. fig 8 shows U.S. interstates and highways in the Twin Cities area by priority score. Higher values = higher VMT (more thru-traffic), higher distance to EV charging locations (farther from chargers), and higher betweenness (more people rely on these routes)
# fig 8: EV‑Charging Priority Score: Twin Cities Interstates
# Reproject to Web Mercator
merged_webmerc = merged_final.to_crs(epsg=3857)
fig, ax = plt.subplots(figsize=(12, 8))
merged_webmerc.plot(
column="combined_metric",
cmap="inferno",
linewidth=2,
norm=LogNorm(),
legend=True,
ax=ax
)
ctx.add_basemap(
ax,
source=ctx.providers.CartoDB.Positron,
zoom=11
)
ax.set_title("EV‑Charging Priority Score: Twin Cities Interstates\n(Log Color Scale)")
ax.axis("off")
plt.show()
B. fig 9 displays the top 100 highway segments in the Twin Cities ranked by their priority scores, highlighting the locations most suitable for new EV‑charger installation.
# fig 9: Top 100 Highway Segments by Priority Score in Twin Cities
g = merged_final.to_crs(3857)
# Compute log metric
g["combined_log"] = np.log1p(g["combined_metric"])
# Extract top 100 locations and reproject them
top10 = merged_final.sort_values("combined_metric", ascending=False).head(100)
top10 = top10.to_crs(3857)
# Create plot
fig, ax = plt.subplots(figsize=(12, 9))
g.plot(
ax=ax,
column="combined_log",
cmap="inferno",
linewidth=3,
legend=True,
alpha=0.9,
aspect=None
)
top10.plot(
ax=ax,
color="blue",
linewidth=8,
alpha=1.0,
label="Top 100 Segments",
aspect=None
)
ctx.add_basemap(
ax,
source=ctx.providers.CartoDB.Positron,
zoom=11
)
ax.set_axis_off()
plt.title("Top 100 Highway Segments by Priority Score (Log Scale)\nTwin Cities, MN")
plt.legend()
plt.show()
Stage 2 Results¶
From the above visualization, we pinpoint top highway segments with the greatest need for new EV‑charger installation, based on VMT, charger distance, and betweenness centrality as below:
- I‑494 near Fort Snelling State Park and MSP Airport
- I‑494 in the Sunfish Lake area
- Highway 10 near Blaine
- I‑694 in Fridley
- I‑494 through South St. Paul
Part V: Conclusion¶
This analysis demonstrates that EV‑charging accessibility along U.S. interstates is shaped by both large‑scale coverage patterns and the structural dynamics of regional highway networks. Nationally, combining VMT with charger distance reveals clear charging deserts where long‑distance travel demand is not supported by existing infrastructure. At the metropolitan scale, incorporating betweenness centrality sharpens these insights, highlighting freeway segments in the Twin Cities where new chargers would most enhance network connectivity and reduce vulnerability to detours or bottlenecks. Based on these findings, we propose targeted expansion of fast‑charging infrastructure in high‑priority corridors, particularly those that carry heavy traffic and serve as critical connectors within the regional mobility system.
While this project provides a data‑driven framework for identifying strategic charging locations, several gaps remain. Charger reliability, power levels, and real‑time availability were not incorporated, yet these factors strongly influence actual usability. Future work could integrate dynamic routing models, temporal traffic patterns, or simulations of EV adoption scenarios to assess how infrastructure needs evolve over time. Incorporating socioeconomic or equity‑based criteria would also broaden the planning relevance of the model. Together, these extensions would support a more comprehensive understanding of where charging investments can most effectively accelerate the transition to long‑distance electric mobility.
Part VI: Acknowledgement, References, & Contribution¶
References¶
Datasets:
- Federal Highway Administration, Office of Highway Policy Information. (2025). Data Access for Highway Performance Monitoring System (HPMS)[Data set]. Retrieved April 26, 2026, from https://data.transportation.gov/stories/s/Data-Access-for-Highway-Performance-Monitoring-Sys/3uu4-47sa/
- U.S. Census Bureau. (2023). TIGER/Line Shapefile: U.S. Primary Roads [Data set]. Retrieved April 12, 2026, from https://catalog.data.gov/dataset/tiger-line-shapefile-2023-nation-u-s-primary-roads
- U.S. Census Bureau. (2025). TIGER/Line Shapefiles: ZIP Code Tabulation Areas (ZCTA), 2025 [Data set]. Retrieved April 28, 2026, from https://www2.census.gov/geo/tiger/TIGER2025/ZCTA520/
- U.S. Department of Energy, Alternative Fuels Data Center. (2026). Electric Vehicle Charging Station Locations [Data set]. Retrieved April 12, 2026, from https://afdc.energy.gov/fuels/electricity-locations
Literature:
- Federal Highway Administration. (2025). National Electric Vehicle Infrastructure (NEVI) Standards and Requirements: Revised Program Guidance. U.S. Department of Transportation. Retrieved April 2026, from https://www.fhwa.dot.gov
- Varga B.O., Sagoian A., Mariasiu F. (2019). Prediction of electric vehicle range: A comprehensive review of current issues and challenges Energies, 12 (5), p. 946, https://doi.org/10.3390/en12050946
Contribution Table¶
| Contribution | Member |
|---|---|
| Conceptualization | All |
| Proposal | All |
| Data Processing | Drew |
| Main Modelling & Computing | Drew & Sam |
| Visualization | Sam & May |
| Final Report | May |
| Presentation Slides | May & Sam |
| Final Presentation | All |