Python空间分析如何快速出图?手把手教你绘制python空间分布图(附:全套代码)
如果你正在搜索“Python空间分析如何快速出图?手把手教你绘制python空间分布图(附:全套代码)”,大概率是已经有一份点、线、面空间数据,想用 Python 快速完成空间分析、分级渲染和地图出图,而不是只停留在表格统计或 GIS 软件手工制图。
引言:用 Python 空间分析快速出图适合哪些场景
Python 空间分析快速出图,最常见的需求是把行政区、采样点、POI、网格、道路或业务数据,做成一张可以汇报、检查或发布的空间分布图。相比在 QGIS 或 ArcGIS Pro 中逐步点击,Python 的优势在于可复现、可批量、可接入数据处理流程。
本文用一个实用流程演示:读取空间数据,统一坐标系,关联统计字段,绘制 python 空间分布图,并导出高清 PNG 图片。你可以把代码替换成自己的 Shapefile、GeoJSON、GeoPackage 或 CSV 点数据。

背景:为什么 Python 空间分布图经常画不对
很多同学第一次用 Python 画 GIS 图,会遇到几个典型问题:图能出来,但位置不对;颜色分级不合理;中文乱码;导出的图片模糊;点和面叠加不上;面积、距离计算结果不可信。
这些问题通常不是绘图函数本身造成的,而是空间数据处理链条没有检查完整。Python 空间分析快速出图不是简单调用 plot(),而是至少要确认数据格式、坐标系、字段类型、空间关系和输出参数。
本文示例使用以下 Python GIS 库:
- GeoPandas:读取和处理矢量空间数据。
- Matplotlib:绘制地图和导出图片。
- Mapclassify:进行自然断点、分位数等分级。
- Contextily:可选,用于添加在线底图。
原理:Python 空间分析出图的核心逻辑
绘制 python 空间分布图,本质上是把“空间几何”和“属性字段”一起表达出来。空间几何决定对象在哪里,属性字段决定对象用什么颜色、大小或符号表示。
一个可靠的 Python 空间分析出图流程通常包括四步:
- 读取数据:用 GeoPandas 读取 Shapefile、GeoJSON、GPKG 或 CSV。
- 统一坐标系:确认所有图层在同一个 CRS,也就是坐标参考系统。
- 计算或关联指标:例如人口密度、点数量、面积占比、缓冲区内统计值。
- 制图输出:设置颜色、图例、标题、边界、字体和分辨率。
如果涉及面积和距离计算,应优先使用投影坐标系,而不是直接在经纬度坐标系下计算。经纬度单位是度,不是米,直接计算面积和距离很容易得到误导性结果。
步骤:手把手绘制 python 空间分布图
步骤 1:准备 Python 环境
建议使用 Conda 创建独立环境,避免 GDAL、Fiona、PyProj 等底层依赖冲突。
conda create -n pygis-map python=3.11 -y
conda activate pygis-map
conda install -c conda-forge geopandas matplotlib mapclassify contextily openpyxl -y
如果你使用 pip,也可以安装,但在 Windows 环境下 GIS 依赖更容易出现编译或版本问题。GIS 初学者更推荐 Conda Forge。
步骤 2:准备示例数据结构
假设你有一个行政区面文件和一个统计表:
data/districts.shp:行政区边界,包含字段adcode。data/stat.xlsx:统计表,包含字段adcode和value。
其中 value 可以是人口、销售额、采样数量、风险指数、土地利用比例等需要表达空间分布的指标。
步骤 3:读取空间数据并检查坐标系
import geopandas as gpd
import pandas as pd
import matplotlib.pyplot as plt
districts = gpd.read_file("data/districts.shp")
stat = pd.read_excel("data/stat.xlsx")
print(districts.head())
print(districts.crs)
print(stat.head())
这里最重要的是 districts.crs。如果输出为 None,说明数据没有定义坐标系。此时不要急着出图,应先确认原始数据到底是什么坐标系,再用 set_crs() 定义。
# 示例:如果确认原始数据是 WGS84 经纬度
districts = districts.set_crs(epsg=4326, allow_override=True)
注意:set_crs() 是“定义坐标系”,不会改变坐标值;to_crs() 是“转换坐标系”,会改变坐标值。二者不能混用。
步骤 4:关联统计字段
用行政区编码 adcode 把空间边界和统计表连接起来。
districts["adcode"] = districts["adcode"].astype(str)
stat["adcode"] = stat["adcode"].astype(str)
gdf = districts.merge(stat, on="adcode", how="left")
print(gdf[["adcode", "value"]].head())
print(gdf["value"].isna().sum())
如果 value 出现大量空值,通常是编码类型不一致、前导零丢失、字段名写错或行政区版本不一致。
步骤 5:绘制分级设色空间分布图
下面这段代码可以直接绘制一张基础的 python 空间分布图。分级方式使用 quantiles,即分位数分级,适合快速观察区域差异。
import matplotlib as mpl
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS"]
plt.rcParams["axes.unicode_minus"] = False
fig, ax = plt.subplots(figsize=(10, 8), dpi=150)
gdf.plot(
column="value",
ax=ax,
cmap="YlOrRd",
scheme="quantiles",
k=5,
legend=True,
edgecolor="#666666",
linewidth=0.4,
missing_kwds={
"color": "#eeeeee",
"edgecolor": "#999999",
"hatch": "///",
"label": "无数据"
}
)
ax.set_title("区域指标空间分布图", fontsize=16, pad=15)
ax.set_axis_off()
plt.tight_layout()
plt.savefig("output/python_space_distribution_map.png", dpi=300, bbox_inches="tight")
plt.show()
这段代码完成了颜色分级、边界线绘制、图例显示、中文标题和高清导出。对于日常汇报图、论文初稿图和数据质检图,这已经足够使用。
步骤 6:添加点数据叠加分析
如果你还需要把采样点、监测站、门店或事件点叠加到行政区上,可以读取点图层并统一坐标系。
points = gpd.read_file("data/points.geojson")
if points.crs != gdf.crs:
points = points.to_crs(gdf.crs)
fig, ax = plt.subplots(figsize=(10, 8), dpi=150)
gdf.plot(
column="value",
ax=ax,
cmap="Blues",
scheme="quantiles",
k=5,
legend=True,
edgecolor="#555555",
linewidth=0.4
)
points.plot(
ax=ax,
color="red",
markersize=12,
alpha=0.75
)
ax.set_title("区域指标与点位叠加空间分布图", fontsize=16, pad=15)
ax.set_axis_off()
plt.tight_layout()
plt.savefig("output/python_overlay_distribution_map.png", dpi=300, bbox_inches="tight")
plt.show()
点面叠加不上时,第一反应应该是检查坐标系,而不是调整颜色或缩放范围。
步骤 7:按行政区统计点数量并出图
很多 Python 空间分析快速出图场景不是直接画已有字段,而是先做空间统计。例如统计每个行政区内有多少个点。
# 确保点和面坐标系一致
if points.crs != districts.crs:
points = points.to_crs(districts.crs)
joined = gpd.sjoin(points, districts[["adcode", "geometry"]], how="left", predicate="within")
count_df = joined.groupby("adcode").size().reset_index(name="point_count")
district_count = districts.merge(count_df, on="adcode", how="left")
district_count["point_count"] = district_count["point_count"].fillna(0)
fig, ax = plt.subplots(figsize=(10, 8), dpi=150)
district_count.plot(
column="point_count",
ax=ax,
cmap="OrRd",
scheme="naturalbreaks",
k=5,
legend=True,
edgecolor="#666666",
linewidth=0.4
)
points.plot(ax=ax, color="#111111", markersize=6, alpha=0.5)
ax.set_title("各行政区点数量空间分布图", fontsize=16, pad=15)
ax.set_axis_off()
plt.tight_layout()
plt.savefig("output/python_point_count_map.png", dpi=300, bbox_inches="tight")
plt.show()
这里的 gpd.sjoin() 是空间连接。它根据几何关系把点匹配到面内,常用于点落区、区域统计、网格统计和空间归属判断。
常见坑:Python 空间分析快速出图最容易出错的地方
坑 1:坐标系看起来一样,实际不是一样
有些数据都显示在中国范围,但一个是 WGS84 经纬度,一个是 CGCS2000 经纬度,一个是 Web Mercator。肉眼看不一定明显,做空间连接、面积计算、缓冲区分析时就会出问题。
- 先打印
gdf.crs。 - 叠加前统一使用
to_crs()。 - 面积和距离计算前转换到合适的投影坐标系。
坑 2:中文字段或中文标题乱码
Matplotlib 默认字体不一定支持中文。可以设置中文字体:
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei", "Arial Unicode MS"]
plt.rcParams["axes.unicode_minus"] = False
如果 Shapefile 属性表中文乱码,常见原因是编码问题。可以尝试:
gdf = gpd.read_file("data/districts.shp", encoding="utf-8")
# 或
gdf = gpd.read_file("data/districts.shp", encoding="gbk")
坑 3:导出的空间分布图很模糊
网页预览看起来可以,但插入报告后模糊,通常是导出分辨率不足。建议使用:
figsize控制画布尺寸。dpi=300或更高用于报告和论文。bbox_inches="tight"去除多余白边。
坑 4:分级颜色误导判断
分位数分级适合比较排名,但可能让数值差异很小的区域看起来差异很大。自然断点适合突出聚类差异,但不同数据集之间不一定可比。等距分级容易理解,但对极端值敏感。
制作 python 空间分布图时,不要只追求颜色好看,还要考虑指标分布和读图目的。
坑 5:Shapefile 字段名被截断
Shapefile 字段名长度有限,长字段可能被截断。若字段频繁丢失或变形,建议改用 GeoPackage:
gdf.to_file("output/result.gpkg", layer="district_result", driver="GPKG")
方法比较:Python、QGIS 和 ArcGIS Pro 出图怎么选
| 方法 | 适合场景 | 优势 | 限制 |
|---|---|---|---|
| Python GeoPandas + Matplotlib | 批量出图、自动化报告、数据分析流程 | 可复现、易批处理、适合和统计分析结合 | 版式设计不如专业 GIS 制图界面直观 |
| QGIS | 交互式制图、快速检查数据、开源桌面 GIS | 可视化操作方便,插件丰富 | 批量自动化需要额外配置 Processing 或 PyQGIS |
| ArcGIS Pro | 正式制图、企业 GIS、复杂地图布局 | 制图体系完整,符号化和布局能力强 | 授权成本较高,自动化通常依赖 ArcPy |
| Python + Folium 或 Plotly | 交互式网页地图、数据探索 | 可缩放、可点击、适合分享 HTML | 不一定适合高质量静态制图和印刷输出 |
如果你的目标是快速分析并导出多张同类地图,Python 空间分析快速出图更合适。如果你的目标是精细排版、注记避让、地图整饰和印刷级制图,QGIS 或 ArcGIS Pro 会更顺手。
检查清单:出图前务必确认这些项
- 空间数据是否能正常读取,几何是否为空。
- 所有图层是否有正确 CRS。
- 点、线、面叠加前是否已经统一坐标系。
- 属性连接字段的数据类型是否一致。
- 统计字段是否存在空值、异常值和极端值。
- 分级方法是否符合业务解释逻辑。
- 中文字体是否能正常显示。
- 图例、标题、颜色和边界线是否清晰。
- 导出图片是否设置了足够的 dpi。
- 输出文件夹是否存在,路径是否写对。
FAQ:Python 空间分析快速出图常见问题
1. Python 空间分析快速出图一定要用 GeoPandas 吗?
不一定,但 GeoPandas 是入门和日常矢量空间分析最方便的选择。它把 Pandas 表格处理和 Shapely 几何处理结合起来,适合绘制 python 空间分布图、空间连接、缓冲区、叠加分析和字段统计。
2. 为什么我的点数据和面数据叠加不上?
最常见原因是坐标系不一致,或者某个图层没有正确定义 CRS。先检查 points.crs 和 districts.crs,再用 to_crs() 转换到同一坐标系。
3. 经纬度数据能不能直接计算面积和距离?
不建议。经纬度单位是度,不能直接当作米使用。做面积、距离、缓冲区等空间分析前,应转换到合适的投影坐标系。例如局部城市分析可选择对应 UTM 分带或本地投影。
4. python 空间分布图用什么颜色方案比较合适?
连续数值常用 YlOrRd、OrRd、Blues 等顺序色带;正负差异可以用发散色带,如 RdBu。不要在同一张图里混用过多高饱和颜色,否则会影响读图。
5. 如何批量给多个字段出图?
可以把字段名放入列表,用循环生成多张图。注意每个字段的标题、图例和输出文件名要单独设置。
fields = ["population", "income", "risk_index"]
for field in fields:
fig, ax = plt.subplots(figsize=(10, 8), dpi=150)
gdf.plot(
column=field,
ax=ax,
cmap="YlOrRd",
scheme="quantiles",
k=5,
legend=True,
edgecolor="#666666",
linewidth=0.4
)
ax.set_title(f"{field} 空间分布图", fontsize=16, pad=15)
ax.set_axis_off()
plt.tight_layout()
plt.savefig(f"output/{field}_map.png", dpi=300, bbox_inches="tight")
plt.close()
6. 为什么空间连接结果为空?
优先检查三点:坐标系是否一致,点是否确实落在面范围内,空间关系参数是否正确。点落区通常使用 predicate="within",如果边界点较多,也可以根据数据特点测试 intersects。
结论:快速出图的关键不是 plot,而是完整流程
Python 空间分析快速出图的核心,不是记住某一个绘图函数,而是建立稳定流程:读取数据、检查坐标系、关联或计算指标、选择合理分级、设置制图样式并导出高清图片。
只要把本文代码中的文件路径、连接字段和指标字段替换成自己的数据,就可以快速绘制 python 空间分布图。后续如果需要批量制图、自动化报告或 WebGIS 数据发布,也可以在这个流程上继续扩展。