znlgis 博客

GIS开发与技术分享

第十章:空间分析步骤详解

空间分析步骤(analysis.*)提供高级地理空间分析功能,共 4 个步骤,需要安装 [analysis] 可选依赖(scipy、scikit-learn、matplotlib)。


10.1 安装依赖

pip install -e ".[analysis]"

若未安装,步骤在注册时不会抛出错误,但执行时会提示缺少 scipyscikit-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] 依赖):

  1. analysis.voronoi:泰森多边形,点→多边形,支持自定义裁剪边界
  2. analysis.heatmap:核密度热力图,点→栅格,支持自定义分辨率和带宽
  3. analysis.interpolate:空间插值,离散点→连续栅格面,支持 linear/cubic/IDW 方法
  4. analysis.cluster:空间聚类,支持 DBSCAN 和 KMeans 两种算法

导航← 第九章:栅格分析步骤第十一章:网络分析步骤 →