You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何将GeoDataFrame转换为NetworkX并应用于Dijkstra最短路径算法

Python环境下路网Shp导入、GeoDataFrame转NetworkX及Dijkstra最短路径实现

前置依赖

先安装需要的第三方库:

pip install geopandas networkx shapely

1. 读取Shapefile格式路网数据

路网类Shapefile一般为线要素格式,直接用geopandas读取即可,读取后先过滤掉几何为空的无效要素:

import geopandas as gpd
import networkx as nx
from shapely.geometry import LineString

# 替换为本地shapefile文件路径
road_gdf = gpd.read_file("./city_road.shp")
# 过滤空几何无效数据
road_gdf = road_gdf[~road_gdf.geometry.isna()].reset_index(drop=True)

注意:如果数据为WGS84经纬度坐标系(EPSG:4326),请先调用road_gdf = road_gdf.to_crs(epsg=对应区域投影EPSG编码)转换为平面投影坐标系,否则后续计算的长度单位为度,和实际距离偏差极大。

2. GeoDataFrame转NetworkX图结构

常规城市路网不考虑单行线时用无向图即可,需要考虑通行方向时初始化有向图。直接取线段首尾坐标作为节点唯一标识,不需要额外生成节点ID,避免ID重复问题;边权重优先使用Shapefile自带的长度/通行时间字段,无对应字段时用几何长度作为权重:

# 初始化无向图,考虑单行线替换为 nx.DiGraph()
G = nx.Graph()

for _, row in road_gdf.iterrows():
    geom = row.geometry
    # 拆分多段线为单段线处理
    if geom.geom_type == "MultiLineString":
        line_list = list(geom.geoms)
    else:
        line_list = [geom]
    
    for line in line_list:
        # 取线段首尾坐标作为节点ID
        start_node = (line.coords[0][0], line.coords[0][1])
        end_node = (line.coords[-1][0], line.coords[-1][1])
        # 计算边权重
        if "length" in road_gdf.columns:
            edge_weight = row["length"]
        else:
            edge_weight = line.length
        # 保存边的所有属性,包含几何、道路名称、等级等信息,后续可视化/分析要用
        edge_attr = row.drop("geometry").to_dict()
        edge_attr["weight"] = edge_weight
        edge_attr["geometry"] = line
        G.add_edge(start_node, end_node, **edge_attr)

3. 基于Dijkstra算法计算最短路径

NetworkX内置的Dijkstra算法可直接调用,注意输入的起终点坐标需要和路网坐标系一致,先匹配距离最近的路网节点再计算路径:

# 替换为实际起终点坐标,需和路网坐标系保持一致
origin = (116.3970, 39.9080)
destination = (116.4080, 39.9150)

# 查找距离输入坐标最近的路网节点
def get_nearest_node(graph, point):
    nodes = list(graph.nodes)
    return min(nodes, key=lambda n: (n[0]-point[0])**2 + (n[1]-point[1])**2)

start_node = get_nearest_node(G, origin)
end_node = get_nearest_node(G, destination)

# 计算最短路径,返回路径经过的节点序列
path_nodes = nx.dijkstra_path(G, source=start_node, target=end_node, weight="weight")
# 计算最短路径总权重(总长度/总通行时间)
path_total_cost = nx.dijkstra_path_length(G, source=start_node, target=end_node, weight="weight")

# 提取路径所有边的几何,可直接用于导出或可视化
path_edge_pairs = list(zip(path_nodes[:-1], path_nodes[1:]))
path_geometries = [G.edges[u, v]["geometry"] for u, v in path_edge_pairs]

实际使用的几个注意点:

  • 若运行时报错节点不存在,优先检查起终点坐标与路网坐标系是否匹配,禁止跨坐标系传参
  • 若需考虑限行、限速、转向限制等规则,只需在添加边时设置对应方向的权重即可,有向图场景下仅添加允许通行方向的边
  • 提取出的路径几何可直接构造为GeoDataFrame,导出为Shapefile或对接可视化库出图

内容的提问来源于stack exchange,提问作者K.N.M.Hirushan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 16:15:54