Python 怎么做 GIS 点密度地图

Python
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

用 Python 做 GIS 点密度地图,本质是把离散点转成“哪里更密”的连续表达:要么按网格分箱统计点数(binning),要么用核密度估计(KDE)生成平滑密度表面或热力图。日常最快上手的组合是 GeoPandas 读点 + Folium 的 HeatMap 出交互 HTML;要静态等值线或栅格,再用 scipy、KDEpy 或 geoplot。关键前提是先投影到平面坐标系,再调带宽与分辨率,否则距离失真、密度单位无意义。

点密度热力图概念示意

两种主流做法怎么选

点密度地图要解决的是“点在哪里聚集、聚集强度如何”的可视化与定量问题。选错方法会要么锯齿太重,要么过度平滑看不出热点。

方法 适用场景 输出形态 常用库 注意点
网格计数(矩形/六边形) 需要可计数、可叠加属性的分区统计 面图层或栅格 GeoPandas + 自建网格 网格大小决定细节,太大则丢失热点
核密度估计(KDE / 热力图) 需要平滑连续表面、探索聚集趋势 交互热力、等值线、GeoTIFF Folium HeatMap、geoplot、KDEpy、scipy 带宽单位必须与投影 CRS 一致
  • 要快速给领导看交互网页 → 优先 Folium HeatMap。
  • 要写进报告的静态图或继续做叠加分析 → 选 KDE 出栅格/等值线。
  • 点特别多(十万级以上)→ 倾向 KDEpy 的 FFT 加速或网格分箱,避免纯循环。

若你还在搭 Python GIS 基础环境,可先看本站的gis Python入门指南,从解析Gis python库开始和gis python 开发入门全解析,把 GeoPandas、投影概念理顺再回来做密度。

环境安装与点数据预处理

截至 2026 年 11 月,GeoPandas 稳定版约 1.2.x(要求 Python ≥3.11),Folium 稳定版约 0.20.x。Windows 上强烈建议用 conda-forge 新建环境,避免 GDAL/PROJ DLL 冲突。

  1. 新建环境并安装核心包:conda create -n gisdens python=3.11;conda activate gisdens;conda install -c conda-forge geopandas folium matplotlib mapclassify。
  2. 需要快速 KDE 时再装:pip install KDEpy;或 conda install -c conda-forge pointpats。
  3. 读入点数据:用 geopandas.read_file 读 shapefile/GeoJSON,或 geopandas.points_from_xy(lon, lat) 从表格建 GeoDataFrame。
  4. 检查并投影:打印 gdf.crs;若是 EPSG:4326,用 to_crs 转到当地 UTM 或等面积投影(密度计算必须在平面距离下进行)。
  5. 清洗:去掉空几何、明显越界点;若有权重列(如人口、事件次数)保留备用。

样本数据可从 GeoPandas 配套数据集获取,见geodatasets 发布页。预处理完成的验收标准:CRS 为投影坐标、无空几何、点数量与源表一致。

用 Folium 做交互式点密度热力图

Folium 底层是 Leaflet,HeatMap 插件直接吃 [纬度, 经度] 或 [纬度, 经度, 权重] 列表,适合快速出可缩放网页。

  1. 导入:import folium;from folium.plugins import HeatMap;import geopandas as gpd。
  2. 准备热力列表:投影后若仍想用经纬度底图,可先 to_crs(4326) 再提取 [[y, x] for x,y in zip(gdf.geometry.x, gdf.geometry.y)];有权重则加第三列。
  3. 建底图:m = folium.Map(location=[中心纬度, 中心经度], zoom_start=合适级别, tiles=”OpenStreetMap” 或 Carto 无 token 样式)。
  4. 加图层:HeatMap(热力数据, radius=12~25, blur=10~15, min_opacity=0.3, gradient 可自定义).add_to(m)。
  5. 保存并验收:m.save(“point_density.html”);浏览器打开,缩放平移时热点应与原始点聚集位置重合,边缘无明显断层。

点超过约一万时浏览器可能变卡,可先随机抽样或改用网格聚合后再喂给 HeatMap。参数里 radius、blur 要结合地图比例尺试几次,过大则整片糊成一团。

Folium 交互热力图使用场景示意

用核密度估计生成平滑密度面或栅格

需要可量化的密度值(单位面积事件数)或继续做栅格运算时,用 KDE。geoplot.kdeplot 上手快但库处于维护状态;生产更稳的是 KDEpy 或 scipy,再配合 rasterio 出 GeoTIFF。

  1. 取投影后的坐标数组:coords = np.vstack([gdf.geometry.x, gdf.geometry.y])(注意 scipy.gaussian_kde 要求形状为 (维数, 样本数))。
  2. 选带宽:先试 Scott / Silverman 规则,再按业务手动调;带宽单位是投影坐标的米或公里,过小噪声多、过大只剩一团。
  3. 计算:用 KDEpy.FFTKDE 或 scipy.stats.gaussian_kde 在规则网格上评估;或直接用 spatial-kde / pointpats.plot_density 出图。
  4. 可视化:matplotlib 的 contourf / pcolormesh,或 geoplot.kdeplot(gdf, shade=True, cmap=”YlOrRd”, clip=研究区边界)。
  5. 导出栅格:把网格密度写成 GeoTIFF(记得写对 transform 与 CRS),便于叠到 QGIS 或其他分析。

大规模点集可关注 KDEpy 项目动态 里的 FFT 实现。若更习惯桌面端,QGIS 也有基于 LibKDV 的快速密度插件可对照结果,见Fast Density Analysis 插件页;需要在 QGIS 里调 Python 时,可参考本站QGIS Python控制台怎么用与常用命令。

  • 验收:密度高值区应对应原始点密集区;积分后总“事件量”应与点数(或权重和)大致成比例;无大片 NaN。
  • 单位:输出通常是“每平方地图单位的事件数”,制图时在图例写清楚。

常见问题

安装 GeoPandas 报 GDAL / DLL 错误怎么办?

优先扔掉混用的 pip/conda 环境,新建纯 conda-forge 环境再装 geopandas;仍失败再装对应 Python 版本的预编译依赖,并确认已装 Visual C++ 运行库。不要在同一环境里混 defaults 与 conda-forge。

热力图位置和点对不上?

Folium 要 [纬度, 经度] 顺序;若你从投影坐标直接取 x/y 却底图用的是 Web 墨卡托,会整体偏移。先统一到 EPSG:4326 再提取列表,或确认底图与数据 CRS 一致。

KDE 结果过糊或全是噪点?

带宽不合适。过大会抹平真实热点,过小会跟着单个点抖。用投影坐标后从自动规则起步,按研究区尺度(例如城市用几百米、县域用几公里)微调,并固定随机种子方便对比。

点特别多跑得很慢?

换 KDEpy 的 FFTKDE、降低评估网格分辨率,或先做六边形/矩形分箱再可视化。Folium 端可对点做抽样或聚合后再传给 HeatMap。

做 Python GIS 点密度地图,先保证投影正确,再在“交互热力(Folium)”和“可定量 KDE 栅格”两条路上选一条主路径,带宽与网格大小用同一套验收标准反复试。建议新手从 GeoPandas + Folium 热力图跑通全流程,再按需引入 KDEpy 出栅格;环境一次性用 conda-forge 配好,后续改参数会轻松很多。