第十一章:网络分析步骤详解
网络分析步骤(network.*)提供基于图论的路网分析和地理编码功能,共 3 个步骤,需要安装 [network] 可选依赖(networkx、geopy)。
11.1 安装依赖
pip install -e ".[network]"
11.2 步骤总览
| 步骤 ID | 名称 | 功能 | 依赖 |
|---|---|---|---|
network.shortest_path |
最短路径 | 计算两点间最短路径 | networkx |
network.service_area |
服务区分析 | 计算可达服务区 | networkx |
network.geocode |
地理编码 | 地址列表→坐标点 | geopy |
11.3 network.shortest_path:最短路径
在线矢量网络(道路、管线等)中计算两点之间的最短路径,使用 networkx 构建图论模型。
参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
input |
geodataframe | ✅ | — | 输入线矢量网络(道路、管线等) |
origin |
list | ✅ | — | 起点坐标 [x, y] |
destination |
list | ✅ | — | 终点坐标 [x, y] |
weight |
string | ❌ | — | 权重字段名(如 "travel_time", "length");不指定则使用几何长度 |
输出
| 属性 | 类型 | 说明 |
|---|---|---|
output |
GeoDataFrame | 最短路径线(LineString),含 path_cost、node_count 属性 |
stats.path_cost |
float | 路径总代价(权重之和或几何长度) |
stats.node_count |
int | 路径经过的节点数量 |
stats.path_length |
float | 路径几何长度 |
实现原理
- 将线矢量网络的每条线段端点作为图节点,线段作为边
- 边权重默认为几何长度,也可使用指定属性字段
- 找到最近的图节点作为起终点
- 使用
networkx.shortest_path(Dijkstra 算法)计算最短路径 - 将路径节点序列构建为 LineString
示例
pipeline:
name: "最短路径分析"
steps:
- id: load-network
use: io.read_vector
params: { path: "data/road_network.shp" }
- id: reproject
use: vector.reproject
params:
input: "$load-network"
target_crs: "EPSG:3857"
- id: find-path
use: network.shortest_path
params:
input: "$reproject"
origin: [12952000, 4835000] # EPSG:3857 坐标
destination: [12960000, 4840000]
weight: "travel_time" # 按行驶时间最短
on_error: fail
- id: save-path
use: io.write_vector
params:
input: "$find-path"
path: "output/shortest_path.geojson"
format: "GeoJSON"
outputs:
path_cost: "$find-path.path_cost"
path_length: "$find-path.path_length"
注意:若起终点之间没有连通路径,步骤会抛出
ValueError: No path found。建议配合on_error: fail快速发现网络连通性问题。
11.4 network.service_area:服务区分析
从指定起点出发,计算在给定代价限制内能到达的所有节点,并构建服务区多边形(等时圈或等距圈)。
参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
input |
geodataframe | ✅ | — | 输入线矢量网络 |
origin |
list | ✅ | — | 服务中心点坐标 [x, y] |
max_cost |
number | ✅ | — | 最大代价(距离/时间上限) |
weight |
string | ❌ | — | 权重字段名;不指定则使用几何长度 |
输出
| 属性 | 类型 | 说明 |
|---|---|---|
output |
GeoDataFrame | 服务区多边形(Polygon),由可达节点的凸包构建 |
stats.reachable_nodes |
int | 可达节点数量 |
stats.max_cost |
float | 实际使用的最大代价 |
示例
pipeline:
name: "医院 15 分钟步行服务区"
steps:
- id: load-network
use: io.read_vector
params: { path: "data/street_network.shp" }
- id: reproject
use: vector.reproject
params:
input: "$load-network"
target_crs: "EPSG:3857"
# 步行速度约 80 米/分钟,15 分钟 = 1200 米
- id: service-area
use: network.service_area
params:
input: "$reproject"
origin: [12953000, 4836000] # 医院坐标(EPSG:3857)
max_cost: 1200 # 1200 米
- id: save-service-area
use: io.write_vector
params:
input: "$service-area"
path: "output/hospital_15min.geojson"
format: "GeoJSON"
11.5 network.geocode:地理编码
将地址字符串列表批量转换为地理坐标,使用 geopy 库,目前支持 Nominatim(OpenStreetMap 数据)。
参数
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
addresses |
list | ✅ | — | 地址字符串列表 |
provider |
string | ❌ | nominatim |
地理编码服务(当前仅支持 nominatim) |
user_agent |
string | ❌ | geopipe-agent |
HTTP User-Agent(Nominatim 要求非空且唯一) |
输出
| 属性 | 类型 | 说明 |
|---|---|---|
output |
GeoDataFrame | 地理编码结果点数据(CRS: EPSG:4326)。含 address、resolved_address、latitude、longitude 字段 |
stats.total |
int | 输入地址总数 |
stats.success |
int | 成功编码数量 |
stats.failed |
int | 失败数量 |
stats.failed_addresses |
list | 失败的地址列表 |
示例
pipeline:
name: "学校地理编码"
steps:
- id: geocode-schools
use: network.geocode
params:
addresses:
- "北京市海淀区清华大学"
- "北京市海淀区北京大学"
- "北京市朝阳区中国传媒大学"
provider: "nominatim"
user_agent: "my-gis-project" # 自定义标识,避免被限速
on_error: retry # 网络问题时重试
- id: save-locations
use: io.write_vector
params:
input: "$geocode-schools"
path: "output/schools.geojson"
format: "GeoJSON"
outputs:
success_count: "$geocode-schools.success"
failed_count: "$geocode-schools.failed"
使用限制:Nominatim 是开放服务,有使用速率限制(1 请求/秒)。批量地理编码时请设置合理的
user_agent并注意请求频率。商业场景建议使用付费地理编码 API。
11.6 网络分析注意事项
6.1 网络数据质量要求
网络分析步骤将线矢量网络转换为图,网络数据质量直接影响分析结果:
- 连通性:道路线必须在端点处精确相交,存在悬挂线或缺口会导致网络不连通
- 方向性:当前实现为无向图,不区分单行道方向
- 坐标系:建议使用投影坐标系(单位米)进行距离计算,使用 WGS84(度)时权重单位为度
6.2 数据预处理建议
# 最短路径分析前的数据准备
steps:
- id: load-roads
use: io.read_vector
params: { path: "data/roads.shp" }
# 过滤出可通行道路
- id: filter-passable
use: vector.query
params:
input: "$load-roads"
expr: "road_class not in ['footway', 'cycleway']"
# 转换为米制坐标
- id: reproject
use: vector.reproject
params:
input: "$filter-passable"
target_crs: "EPSG:3857"
- id: find-path
use: network.shortest_path
params:
input: "$reproject"
origin: [12952000, 4835000]
destination: [12960000, 4840000]
11.7 本章小结
本章介绍了 3 个网络分析步骤(需安装 [network] 依赖):
network.shortest_path:Dijkstra 最短路径算法,支持自定义权重字段,网络不连通时报错network.service_area:从起点出发的可达服务区,基于代价限制(距离/时间),结果为凸包多边形network.geocode:批量地址→坐标转换,使用 Nominatim,注意使用频率限制,建议配on_error: retry