第十章:空间分析步骤详解
空间分析步骤(analysis.*)提供高级地理空间分析功能,共 4 个步骤,需要安装 [analysis] 可选依赖(scipy、scikit-learn、matplotlib)。
10.1 安装依赖
pip install -e ".[analysis]"
若未安装,步骤在注册时不会抛出错误,但执行时会提示缺少 scipy 或 scikit-learn。
10.2 步骤总览
| 步骤 ID |
名称 |
功能 |
依赖 |
analysis.voronoi |
泰森多边形 |
点→泰森多边形 |
scipy |
analysis.heatmap |
热力图 |
点→核密度栅格 |
scipy, rasterio |
analysis.interpolate |
空间插值 |
点→连续面插值 |
scipy |
analysis.cluster |
空间聚类 |
点聚类分析 |
scikit-learn |
10.3 analysis.voronoi:泰森多边形
根据输入点数据生成泰森多边形(Voronoi 图)。每个多边形包含距离该点比其他点更近的所有位置。
参数
| 参数 |
类型 |
必填 |
默认值 |
说明 |
input |
geodataframe |
✅ |
— |
输入点矢量数据(至少 3 个点) |
envelope |
geodataframe |
❌ |
— |
裁剪边界;不指定则使用点范围的凸包+缓冲区 |
输出
| 属性 |
类型 |
说明 |
output |
GeoDataFrame |
泰森多边形(Polygon),携带原始点的属性 |
stats.input_point_count |
int |
输入点数量 |
stats.polygon_count |
int |
生成的多边形数量 |
示例
pipeline:
name: "气象站泰森多边形"
description: "为气象站生成泰森多边形,用于面积加权降水量估算"
steps:
- id: load-stations
use: io.read_vector
params: { path: "data/weather_stations.shp" }
- id: load-basin
use: io.read_vector
params: { path: "data/river_basin.shp" }
- id: voronoi
use: analysis.voronoi
params:
input: "$load-stations"
envelope: "$load-basin" # 裁剪到流域边界
- id: save-voronoi
use: io.write_vector
params:
input: "$voronoi"
path: "output/station_voronoi.geojson"
format: "GeoJSON"
注意:输入必须是点(Point)类型。若输入是多边形,先用 vector.reproject 转换或提取质心。
10.4 analysis.heatmap:热力图
基于核密度估计(KDE)从点数据生成热力图栅格,使用高斯核函数和 2D 直方图。
参数
| 参数 |
类型 |
必填 |
默认值 |
说明 |
input |
geodataframe |
✅ |
— |
输入点矢量数据 |
resolution |
number |
❌ |
100 |
输出栅格宽度方向的像素数(越大越精细) |
bandwidth |
number |
❌ |
— |
高斯核带宽(与坐标单位相同);不指定则自动估算 |
输出
| 属性 |
类型 |
说明 |
output |
raster_info |
热力图栅格数据(单波段,float64) |
stats.point_count |
int |
输入点数量 |
stats.max_density |
float |
最大密度值 |
stats.width / stats.height |
int |
输出栅格尺寸 |
示例
- id: load-incidents
use: io.read_vector
params: { path: "data/traffic_accidents.shp" }
- id: reproject
use: vector.reproject
params:
input: "$load-incidents"
target_crs: "EPSG:3857"
- id: heatmap
use: analysis.heatmap
params:
input: "$reproject"
resolution: 500
bandwidth: 1000 # 1000 米(EPSG:3857 单位为米)
- id: save-heatmap
use: io.write_raster
params:
input: "$heatmap"
path: "output/accident_heatmap.tif"
metadata: "$heatmap.metadata"
10.5 analysis.interpolate:空间插值
将离散点数据插值为连续栅格面,支持 griddata 和 IDW(反距离权重)两种方法。
参数
| 参数 |
类型 |
必填 |
默认值 |
说明 |
input |
geodataframe |
✅ |
— |
输入点矢量数据 |
value_field |
string |
✅ |
— |
用于插值的属性字段名 |
resolution |
number |
❌ |
100 |
输出栅格分辨率(像素数) |
method |
string |
❌ |
linear |
插值方法:linear/nearest/cubic/idw |
power |
number |
❌ |
2 |
IDW 幂次(仅 method=idw 时有效) |
示例
- id: load-stations
use: io.read_vector
params: { path: "data/precipitation_stations.shp" }
- id: interpolate-precip
use: analysis.interpolate
params:
input: "$load-stations"
value_field: "precip_mm" # 降水量字段
resolution: 200
method: "idw"
power: 2
- id: save-surface
use: io.write_raster
params:
input: "$interpolate-precip"
path: "output/precipitation_surface.tif"
metadata: "$interpolate-precip.metadata"
10.6 analysis.cluster:空间聚类
对点数据进行空间聚类分析,支持 DBSCAN(基于密度)和 KMeans(基于距离)两种算法,结果在原始数据上增加 cluster 字段(DBSCAN 中噪声点标记为 -1)。
参数
| 参数 |
类型 |
必填 |
默认值 |
说明 |
input |
geodataframe |
✅ |
— |
输入点矢量数据 |
method |
string |
❌ |
dbscan |
算法:dbscan/kmeans |
n_clusters |
number |
❌ |
5 |
簇数量(仅 KMeans) |
eps |
number |
❌ |
0.5 |
邻域半径(仅 DBSCAN,与坐标单位相同) |
min_samples |
number |
❌ |
5 |
形成核心点的最小邻居数(仅 DBSCAN) |
输出
| 属性 |
类型 |
说明 |
output |
GeoDataFrame |
含 cluster 标签字段的矢量数据 |
stats.n_clusters |
int |
实际发现的簇数量 |
stats.noise_count |
int |
噪声点数量(DBSCAN 中 cluster=-1 的点) |
算法选择建议
| 场景 |
推荐算法 |
说明 |
| 未知簇数、不规则形状 |
DBSCAN |
自动发现簇数,能识别噪声 |
| 已知簇数、球形分布 |
KMeans |
速度快,结果稳定 |
DBSCAN 参数调优
eps:若使用 EPSG:4326,eps=0.01 约为 1 公里;若使用 EPSG:3857(米),eps=1000 为 1 公里
min_samples:数据密度高时增大,稀疏时减小
示例
# DBSCAN 聚类:发现犯罪热点区域
- id: cluster-crimes
use: analysis.cluster
params:
input: "$reproject-crimes"
method: "dbscan"
eps: 500 # 500 米(EPSG:3857)
min_samples: 10 # 至少 10 个事件才形成一个热点
# KMeans 聚类:将便利设施分为 5 个服务区
- id: cluster-facilities
use: analysis.cluster
params:
input: "$load-facilities"
method: "kmeans"
n_clusters: 5
10.7 空间分析综合示例:城市犯罪热点分析
pipeline:
name: "城市犯罪热点分析"
description: "对犯罪事件进行热力图和聚类分析,识别高风险区域"
variables:
crime_data: "data/crime_incidents.shp"
study_area: "data/city_boundary.shp"
steps:
- id: load-crimes
use: io.read_vector
params: { path: "${crime_data}" }
- id: load-city
use: io.read_vector
params: { path: "${study_area}" }
- id: reproject-crimes
use: vector.reproject
params:
input: "$load-crimes"
target_crs: "EPSG:3857"
- id: reproject-city
use: vector.reproject
params:
input: "$load-city"
target_crs: "EPSG:3857"
# 仅分析城区内的犯罪
- id: clip-to-city
use: vector.clip
params:
input: "$reproject-crimes"
clip: "$reproject-city"
# 生成热力图
- id: heatmap
use: analysis.heatmap
params:
input: "$clip-to-city"
resolution: 300
bandwidth: 800
- id: save-heatmap
use: io.write_raster
params:
input: "$heatmap"
path: "output/crime_heatmap.tif"
metadata: "$heatmap.metadata"
# DBSCAN 聚类识别热点
- id: cluster-hotspots
use: analysis.cluster
params:
input: "$clip-to-city"
method: "dbscan"
eps: 500
min_samples: 20
# 过滤出热点(去掉噪声点 cluster=-1)
- id: filter-hotspots
use: vector.query
params:
input: "$cluster-hotspots"
expr: "cluster >= 0"
- id: save-clusters
use: io.write_vector
params:
input: "$filter-hotspots"
path: "output/crime_clusters.geojson"
format: "GeoJSON"
outputs:
hotspot_count: "$cluster-hotspots.n_clusters"
noise_count: "$cluster-hotspots.noise_count"
total_incidents: "$clip-to-city.feature_count"
10.8 本章小结
本章介绍了 4 个空间分析步骤(需安装 [analysis] 依赖):
analysis.voronoi:泰森多边形,点→多边形,支持自定义裁剪边界
analysis.heatmap:核密度热力图,点→栅格,支持自定义分辨率和带宽
analysis.interpolate:空间插值,离散点→连续栅格面,支持 linear/cubic/IDW 方法
analysis.cluster:空间聚类,支持 DBSCAN 和 KMeans 两种算法
导航:← 第九章:栅格分析步骤 | 第十一章:网络分析步骤 →