Python地理处理还在手动拼接地图?四步自动化出图脚本(附:国土空间规划配色方案)

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

如果你在做“Python地理处理还在手动拼接地图?四步自动化出图脚本(附:国土空间规划配色方案)”这类工作,通常痛点不是不会制图,而是每次都要重复打开软件、加载数据、套样式、导出图片,项目一多就很容易出错。本文用一个可复用的 Python 自动化出图流程,把矢量数据读取、字段分类、规划用途配色、地图布局和批量导出串起来,适合国土空间规划、专题图批量制图和 GIS 数据检查场景。

引言:为什么要用 Python 地理处理自动化出图

很多 GIS 同学和初级工程师在做规划专题图时,会先在 QGIS 或 ArcGIS Pro 里调好一张图,再截图、复制、手动拼接,最后放到报告里。这个方式在单张图时问题不大,但一旦涉及多个行政区、多个年份、多个规划情景,手工流程就会暴露三个问题:

  • 效率低:同一套图层、同一套配色,需要重复操作很多次。
  • 一致性差:图例、色值、比例尺、标题位置很容易前后不一致。
  • 难以复现:别人很难知道你当时到底用了哪份数据、哪套分类字段和哪组颜色。

Python 地理处理自动化出图的核心价值,是把“人工点击流程”变成“可重复运行的脚本流程”。只要输入数据字段规范、坐标系正确、分类规则明确,同一套脚本就可以稳定生成多张地图。

Python地理处理自动化出图与国土空间规划配色方案流程图
Python 地理处理自动化出图的基本流程:读取数据、应用配色、设置版式、批量导出。

背景:手动拼接地图最容易出错的地方

在国土空间规划、用地现状分析、生态红线核查、城镇开发边界制图等项目中,地图通常不是一张,而是一批。例如按区县出图、按乡镇出图、按用地类型出图、按规划方案出图。

手动拼接地图常见错误包括:

  • 颜色不统一:同一个“城镇建设用地”在不同图中使用了不同颜色。
  • 图层顺序错乱:边界线、道路、水系和用地面层叠放顺序不一致。
  • 范围不一致:有些图裁剪到行政区边界,有些图显示了多余区域。
  • 坐标系混乱:面积计算、比例尺显示和地图范围出现偏差。
  • 导出分辨率不同:报告中有的图清晰,有的图模糊。

因此,自动化出图不是为了替代制图审美,而是为了把标准化、重复性、容易出错的部分固定下来。Python 脚本尤其适合处理“同一套规则、多张地图输出”的任务。

原理:Python 自动化出图到底自动了什么

Python 地理处理自动化出图通常包含四个核心环节:

  1. 读取空间数据:使用 GeoPandas 读取 Shapefile、GeoPackage、GeoJSON 等矢量数据。
  2. 统一坐标系:确保输入图层使用适合制图和面积表达的投影坐标系。
  3. 按字段套用样式:根据用地类型、规划分区、管控类型等字段配置颜色。
  4. 输出地图文件:使用 Matplotlib 导出 PNG、PDF 或 SVG,便于放入报告或进一步排版。

其中 GeoPandas 负责空间数据读取和属性处理,Matplotlib 负责绘图和导出。对于更复杂的制图,例如自动图例、指北针、比例尺、地图整饰,也可以继续扩展 Cartopy、contextily 或 QGIS Python API。

本文示例选择 GeoPandas 加 Matplotlib,是因为它安装相对简单、脚本结构清晰,适合快速完成国土空间规划配色方案的自动化专题图输出。

步骤:四步完成 Python 地理处理自动化出图脚本

步骤一:准备数据和字段

示例假设你有一份规划用地图层,文件为 landuse.gpkg,图层中至少包含一个用地类型字段,例如 land_type。这个字段的值可以是“耕地”“林地”“草地”“城镇建设用地”“村庄建设用地”“水域”等。

建议数据准备时先检查三件事:

  • 几何是否有效:面要素是否存在自相交、空几何或破碎面。
  • 分类字段是否规范:同一种用地不要同时出现“城镇建设用地”“城镇用地”“城镇建设”等多个写法。
  • 坐标系是否明确:数据必须有正确的 CRS,避免绘图范围和面积判断错误。
import geopandas as gpd

input_path = "data/landuse.gpkg"
gdf = gpd.read_file(input_path)

print(gdf.crs)
print(gdf.columns)
print(gdf["land_type"].value_counts())

如果 gdf.crs 输出为 None,说明数据没有定义坐标系。这时不要直接出图,应先确认源数据真实坐标系,再进行定义或转换。

步骤二:设置国土空间规划配色方案

国土空间规划配色方案的关键是“稳定”和“可解释”。颜色不一定要追求复杂,但要保证同一类用地在所有图中保持一致。下面给出一套常用的示例配色,实际项目应以甲方、地方标准或单位制图规范为准。

用地类型 建议色值 说明
耕地 #FFF2B2 浅黄色,适合表达农业生产空间
园地 #D9F0A3 黄绿色,区别于耕地和林地
林地 #78C679 绿色,表达生态空间
草地 #C2E699 浅绿色,弱于林地
水域 #74A9CF 蓝色,表达河湖水面
城镇建设用地 #E34A33 红色,突出建设空间
村庄建设用地 #FDBB84 橙色,与城镇建设用地区分
交通运输用地 #969696 灰色,适合道路、铁路等线性空间
其他用地 #DDDDDD 浅灰色,作为兜底类别
color_map = {
    "耕地": "#FFF2B2",
    "园地": "#D9F0A3",
    "林地": "#78C679",
    "草地": "#C2E699",
    "水域": "#74A9CF",
    "城镇建设用地": "#E34A33",
    "村庄建设用地": "#FDBB84",
    "交通运输用地": "#969696",
    "其他用地": "#DDDDDD"
}

gdf["plot_color"] = gdf["land_type"].map(color_map).fillna("#DDDDDD")

这里使用 fillna("#DDDDDD") 是为了处理未匹配类别。自动化出图时,不建议让脚本因为某个新增分类直接崩溃,但也不能忽略它。更稳妥的方式是输出未匹配类别清单,便于制图前检查。

unknown_types = sorted(set(gdf["land_type"]) - set(color_map.keys()))
if unknown_types:
    print("以下用地类型未配置颜色:")
    for item in unknown_types:
        print(item)

步骤三:绘制单张专题图

下面的代码会绘制一张用地类型专题图,并导出为 PNG。为了让脚本更适合报告使用,示例中关闭坐标轴,设置标题,添加简单图例,并控制导出分辨率。

import matplotlib.pyplot as plt
from matplotlib.patches import Patch

output_path = "output/landuse_map.png"

fig, ax = plt.subplots(figsize=(10, 8))

gdf.plot(
    ax=ax,
    color=gdf["plot_color"],
    edgecolor="#666666",
    linewidth=0.15
)

ax.set_title("国土空间规划用地类型图", fontsize=16)
ax.set_axis_off()

legend_items = []
for land_type, color in color_map.items():
    if land_type in set(gdf["land_type"]):
        legend_items.append(Patch(facecolor=color, edgecolor="#666666", label=land_type))

ax.legend(
    handles=legend_items,
    title="用地类型",
    loc="lower left",
    frameon=True,
    fontsize=9,
    title_fontsize=10
)

plt.tight_layout()
plt.savefig(output_path, dpi=300, bbox_inches="tight")
plt.close()

这一步已经可以替代很多手工截图流程。对于普通报告插图,dpi=300 通常能满足打印和 Word/PDF 排版需求。如果是 Web 页面展示,可以导出较小尺寸的 PNG 或 WebP,以减少页面加载压力。

步骤四:按行政区批量自动出图

真正节省时间的是批量出图。假设你还有一份行政区边界 district.gpkg,字段 name 存储区县名称。下面脚本会按行政区裁剪用地图层,并为每个行政区导出一张图。

import os
import geopandas as gpd
import matplotlib.pyplot as plt
from matplotlib.patches import Patch

land_path = "data/landuse.gpkg"
district_path = "data/district.gpkg"
output_dir = "output/maps"

os.makedirs(output_dir, exist_ok=True)

land = gpd.read_file(land_path)
district = gpd.read_file(district_path)

if land.crs != district.crs:
    district = district.to_crs(land.crs)

color_map = {
    "耕地": "#FFF2B2",
    "园地": "#D9F0A3",
    "林地": "#78C679",
    "草地": "#C2E699",
    "水域": "#74A9CF",
    "城镇建设用地": "#E34A33",
    "村庄建设用地": "#FDBB84",
    "交通运输用地": "#969696",
    "其他用地": "#DDDDDD"
}

land["plot_color"] = land["land_type"].map(color_map).fillna("#DDDDDD")

for idx, row in district.iterrows():
    district_name = row["name"]
    boundary = gpd.GeoDataFrame([row], crs=district.crs)

    clipped = gpd.overlay(land, boundary, how="intersection")

    if clipped.empty:
        print(f"{district_name} 无用地图斑,跳过")
        continue

    fig, ax = plt.subplots(figsize=(10, 8))

    clipped.plot(
        ax=ax,
        color=clipped["plot_color"],
        edgecolor="#666666",
        linewidth=0.12
    )

    boundary.boundary.plot(
        ax=ax,
        color="#000000",
        linewidth=0.8
    )

    ax.set_title(f"{district_name} 国土空间规划用地类型图", fontsize=16)
    ax.set_axis_off()

    legend_items = []
    existing_types = set(clipped["land_type"])
    for land_type, color in color_map.items():
        if land_type in existing_types:
            legend_items.append(Patch(facecolor=color, edgecolor="#666666", label=land_type))

    ax.legend(
        handles=legend_items,
        title="用地类型",
        loc="lower left",
        frameon=True,
        fontsize=9,
        title_fontsize=10
    )

    out_file = os.path.join(output_dir, f"{district_name}_用地类型图.png")
    plt.tight_layout()
    plt.savefig(out_file, dpi=300, bbox_inches="tight")
    plt.close()

    print(f"已导出:{out_file}")

到这里,一个基础版 Python 地理处理自动化出图脚本就完成了。它可以批量生成行政区专题图,并保持相同的国土空间规划配色方案、图例规则和导出参数。

常见坑:自动化出图不准、不美观、导出失败怎么排查

坑一:坐标系不一致导致裁剪结果为空

如果用地图层和行政区边界坐标系不同,直接进行 overlay 可能会得到空结果,或者裁剪位置明显错位。处理方法是先检查 CRS,并把辅助图层转换到主图层坐标系。

print(land.crs)
print(district.crs)

if land.crs != district.crs:
    district = district.to_crs(land.crs)

坑二:中文字段或中文文件名乱码

Shapefile 对中文字段名和编码支持较弱,容易出现乱码或字段名被截断。建议项目数据优先使用 GeoPackage,文件后缀为 .gpkg。如果必须使用 Shapefile,应确认编码,并避免过长字段名。

坑三:图例类别太多,地图看起来很乱

自动图例不是越全越好。如果分类超过 15 个,报告读者很难快速理解。可以考虑合并小类,或者分成多张专题图,例如建设用地专题图、生态空间专题图、农业空间专题图。

坑四:面边线太粗,导出后像“黑块”

大量小图斑叠加时,边线宽度过大会严重影响效果。可以把 linewidth 调低到 0.050.2,或者在小比例尺总览图中取消图斑边线。

坑五:空间叠加速度慢

如果数据量很大,gpd.overlay 可能比较慢。可以先按边界外包框粗筛,再做精确裁剪;也可以安装空间索引依赖,并尽量使用 GeoPackage 或 Parquet 这类更适合批处理的数据格式。

方法比较:Python、QGIS、ArcGIS Pro 哪种出图方式更适合

方法 适合场景 优点 限制
Python GeoPandas + Matplotlib 批量专题图、快速报告插图、数据检查图 脚本可复现,批量处理方便,适合自动化流水线 高级版式、复杂标注和地图整饰需要额外开发
QGIS 布局管理器 正式制图、地图册、需要人工微调的专题图 制图能力强,样式配置直观,支持地图集 批量规则复杂时仍需要 PyQGIS 辅助
ArcGIS Pro 布局与 ArcPy 规范化生产、企业级 GIS 项目、制图模板复用 布局模板成熟,ArcPy 自动化能力强 软件授权成本较高,环境部署相对重
WebGIS 前端截图 在线地图展示、动态专题图预览 交互体验好,适合网页端发布 用于正式报告出图时,分辨率和版式控制较麻烦

如果你的目标是快速生成一批风格统一的专题图,Python 地理处理自动化出图非常合适。如果目标是正式图集出版,建议使用 Python 完成数据预处理和批量初稿,再进入 QGIS 或 ArcGIS Pro 做最终版式检查。

检查清单:运行脚本前后必须确认的事项

  • 数据格式:优先使用 GeoPackage,减少 Shapefile 字段名和编码问题。
  • 坐标系:所有参与裁剪、叠加和绘图的图层 CRS 必须明确。
  • 分类字段:land_type 或项目实际字段不能有空值、错别字和混合写法。
  • 配色方案:国土空间规划配色方案要统一存放,不要在多个脚本中重复手写。
  • 未知类别:脚本应输出未匹配颜色的类别清单,避免图斑被默认灰色掩盖。
  • 图层顺序:面层在下,边界线和重点要素在上。
  • 导出分辨率:报告图建议使用 300 dpi,网页图可根据页面尺寸压缩。
  • 文件命名:批量出图要避免特殊符号,建议使用行政区名加专题图类型。
  • 结果复核:至少抽查几张图,确认范围、图例、颜色和标题都正确。

FAQ:Python 地理处理自动化出图常见问题

Python 自动化出图可以完全替代 QGIS 制图吗?

不建议这样理解。Python 适合批量、标准化、可复现的地图输出;QGIS 更适合人工精修、复杂标注和正式版式。实际项目中,两者结合效率最高。

国土空间规划配色方案有没有固定标准?

不同地区、不同项目和不同制图规范可能存在差异。本文提供的是常用示例配色,正式项目应优先采用地方技术指南、甲方模板或单位内部制图规范。

为什么我导出的地图没有图例?

常见原因是分类字段值和 color_map 中的键不一致。例如数据里是“城镇用地”,配色表里是“城镇建设用地”。可以先运行 value_counts() 检查真实字段值。

Python 批量出图能导出 PDF 吗?

可以。把 plt.savefig() 的输出路径改为 .pdf 即可,例如 plt.savefig("output/map.pdf", bbox_inches="tight")。如果要进入矢量排版软件继续编辑,PDF 或 SVG 会比 PNG 更合适。

大数据量图斑绘图很慢怎么办?

可以先按行政区裁剪,再绘图;也可以对小比例尺地图做简化处理,减少节点数量。对于非常大的数据集,可考虑使用 PostGIS 先完成裁剪、聚合和分类,再用 Python 读取结果出图。

自动化出图时如何保证每张图范围一致?

可以在绘图时固定 xlimylim,或者统一使用行政区边界的外包框加固定缓冲距离。批量制图时,范围规则必须写进脚本,而不是靠人工拖动地图窗口。

结论:把重复制图流程交给脚本,把精力留给判断

Python 地理处理自动化出图的重点不是炫技,而是把重复、标准化、容易出错的制图步骤固化下来。对于国土空间规划专题图,最值得自动化的部分包括数据读取、坐标系统一、规划用途配色、行政区批量裁剪和统一导出。

建议你先从本文的四步脚本开始:准备字段、配置国土空间规划配色方案、绘制单张图、扩展为批量出图。等流程稳定后,再逐步增加比例尺、指北针、标注、底图、图框和 PDF 模板。这样既能提升效率,也能让每一张图都有清晰、可追溯的生成过程。