使用ArcGIS和Python将SHP地图裁剪并转换为NetworkX图结构

张开发
2026/4/6 17:37:47 15 分钟阅读

分享文章

使用ArcGIS和Python将SHP地图裁剪并转换为NetworkX图结构
1. 从SHP地图到NetworkX图的全流程解析第一次接触地理数据处理的朋友可能会觉得这个流程有点复杂但其实拆解开来就是三个关键步骤用ArcGIS裁剪出目标区域、用Python读取处理数据、最后转换为NetworkX图结构。我在城市规划项目里反复用过这个流程实测下来最稳定的方案是用ArcGIS Pro做空间裁剪再用geopandasnetworkx做转换。先说说为什么要这么处理。原始的道路SHP文件往往包含整个省份甚至全国的数据而我们可能只需要分析某个城区。直接处理大文件不仅效率低还会引入大量无关数据。就像你要研究小区内部道路肯定不需要把全国高速公路网都加载进来对吧这里有个新手容易踩的坑SHP文件里的道路几何类型可能混合了LineString和MultiLineString。我遇到过某个城市的道路数据里80%是普通线段但有20%是复杂的高架桥多层结构MultiLineString。如果不做类型判断直接处理程序就会报错卡住。2. ArcGIS精准裁剪实战技巧2.1 三种裁剪方法对比在ArcGIS Pro里裁剪SHP文件我常用这三种方法标准裁剪工具适合有现成边界文件的情况。比如要从全国地图里截取江苏省直接用省界SHP作为裁剪边界最方便。操作路径在Analysis Tools 搜索Clip参数设置注意Input Features选源数据Clip Features选边界。手动绘制裁剪当没有现成边界时可以在Catalog里右键新建Feature Class选择Polygon类型。进入编辑模式后用矩形或多边形工具画出目标区域。有个实用技巧按住Shift键可以锁定正交方向画规则矩形特别方便。属性选择导出临时快速提取时可以用Select by Attributes先筛选比如NAME南京市再右键导出选中要素。不过这种方法不够精确适合快速查看局部数据。2.2 处理复杂几何的注意事项遇到带洞的多边形或者三维道路数据时常规裁剪可能会丢失属性。我的经验是勾选Maintain Clipping Extent保留完整几何对于高程数据额外勾选Preserve Z Values输出前检查属性表是否完整最近处理厦门岛道路数据时就遇到这个问题环岛路的立交桥结构在普通裁剪后变成了平面线段。后来发现是忘记勾选Preserve Complex Geometry选项重新处理后就好了。3. Python转换的核心代码详解3.1 用geopandas读取SHPimport geopandas as gpd roads gpd.read_file(clipped_roads.shp) print(roads.crs) # 一定要检查坐标系这里有个关键点CRS坐标系必须明确。我遇到过WGS84和GCJ02坐标系混用导致的偏移问题。建议先用ArcGIS统一转成CGCS2000或当地投影坐标系。3.2 构建NetworkX图结构import networkx as nx from shapely.geometry import LineString, MultiLineString G nx.Graph() for _, row in roads.iterrows(): geom row.geometry if geom.geom_type LineString: segments [geom] elif geom.geom_type MultiLineString: segments list(geom.geoms) else: continue for line in segments: coords list(line.coords) for i in range(len(coords)-1): start coords[i] end coords[i1] # 计算线段实际长度作为权重 length line.project(Point(end)) - line.project(Point(start)) G.add_edge(start, end, weightabs(length), road_typerow[type], lanesrow[lanes])这段代码做了几件重要的事处理混合几何类型LineString/MultiLineString将曲线离散化为线段保留原始道路属性车道数、道路类型等用实际长度作为边权重3.3 可视化检查结果import matplotlib.pyplot as plt pos {node:node for node in G.nodes()} nx.draw(G, pos, node_size0, width0.5, edge_colorgray, alpha0.7) plt.gca().set_aspect(equal) plt.show()建议在正式分析前先做可视化检查。去年做深圳路网分析时就发现某条道路因为坐标反转导致绘制异常。通过这种简单的可视化能快速发现数据问题。4. 实际应用中的性能优化4.1 处理大型路网的技巧当处理超过1万条道路的SHP文件时原始方法会非常慢。通过这几个优化可以将速度提升10倍以上空间索引过滤先用geopandas的cx索引器按空间范围筛选bbox (xmin, ymin, xmax, ymax) roads roads.cx[bbox[0]:bbox[2], bbox[1]:bbox[3]]批量添加边用nx.add_edges_from替代循环edges [ (start, end, {weight:length}) for line in segments for start,end in pairwise(line.coords) ] G.add_edges_from(edges)使用多重图当有立交桥等重叠道路时G nx.MultiGraph() # 允许平行边4.2 常见错误排查坐标系不匹配确保geopandas读取的CRS与ArcGIS导出时一致几何体异常用geom.is_valid检查无效几何属性丢失检查字段名是否包含中文或特殊字符内存不足对于省级以上路网建议按行政区划分块处理最近帮客户处理青海省路网时就遇到内存爆满的问题。后来改用Dask-geopandas进行分块处理最终成功加载了包含87万条道路的SHP文件。5. 进阶应用路径分析与空间统计有了NetworkX图结构后就可以施展各种图算法了。这里分享两个实用场景5.1 最优路径规划import numpy as np from networkx.algorithms.shortest_paths import dijkstra_path # 考虑车道数加权的路径 def weight_func(u, v, d): base d[weight] lanes d.get(lanes, 2) return base / np.log(lanes 1) # 车道越多权重越低 path dijkstra_path(G, source, target, weightweight_func)这个改进版的Dijkstra算法会优先选择车道数多的主干道比单纯用距离更符合实际驾驶偏好。5.2 路网结构特征分析degree dict(G.degree()) betweenness nx.betweenness_centrality(G, weightweight) # 找出关键枢纽节点 hubs [n for n in G if degree[n] 4 and betweenness[n] 0.1]通过这些指标可以识别交通枢纽位置为规划公交站点提供依据。在郑州项目中发现这种分析方法找出的关键节点与实际拥堵点匹配度达到78%。

更多文章