GeoPandas绘图太丑?Matplotlib咋调?
GeoPandas绘图太丑?Matplotlib咋调? 这是很多 GIS 初学者第一次用 GeoPandas 出图时遇到的问题:数据能画出来,但颜色像默认测试图,图例挤在一起,坐标轴很碍眼,行政区边界不清楚,导出图片还发糊。其实 GeoPandas 的绘图底层主要依赖 Matplotlib,只要掌握几个关键参数,就能把“能看”的地图调成“能交作业、能放报告”的专题图。

引言:GeoPandas绘图为什么看起来“太丑”
GeoPandas 的 GeoDataFrame.plot() 非常适合快速查看空间数据,但它默认不是为正式制图设计的。默认样式通常只解决一个问题:把几何对象画出来。
如果你想做的是课程作业图、项目汇报图、数据分析图,通常还需要进一步处理:
- 调整地图配色,让不同等级更容易识别;
- 设置边界线,避免面要素糊成一片;
- 去掉不必要的坐标轴;
- 添加标题、图例和注记;
- 控制图片尺寸、分辨率和导出格式;
- 保证坐标系和比例不变形。
本文用一个典型的面数据专题图流程,讲清楚 GeoPandas 绘图太丑时,应该如何用 Matplotlib 调整。
背景:GeoPandas绘图与Matplotlib是什么关系
GeoPandas 是 Python GIS 中常用的矢量数据处理库,常用于读取 Shapefile、GeoJSON、GeoPackage 等空间数据。Matplotlib 是 Python 里最常用的绘图库。GeoPandas 的 plot() 方法本质上会把空间几何交给 Matplotlib 的坐标轴对象进行绘制。
也就是说,GeoPandas 负责“地图数据怎么画”,Matplotlib 负责“图面怎么排版”。
很多人只写下面这一句:
gdf.plot()
这样确实能看到地图,但通常会有几个问题:
- 默认颜色没有表达数据含义;
- 图例没有标题,或者位置不好;
- 坐标轴显示经纬度或投影坐标,看起来很乱;
- 图像比例不适合论文、PPT 或公众号配图;
- 导出图片分辨率过低;
- 中文标题或中文图例可能乱码。
所以,解决 GeoPandas 绘图太丑的核心思路不是换一个软件,而是把 GeoDataFrame.plot() 和 Matplotlib 的 fig、ax、legend、savefig 配合起来。
原理:先让GeoPandas画地图,再让Matplotlib管版式
在 Matplotlib 中,一张图通常由两个核心对象组成:
- Figure:整张画布,可以理解为最终图片;
- Axes:具体绘图区域,可以理解为地图所在的坐标框。
GeoPandas 的 plot() 可以接收一个 ax 参数,把地图画到指定的 Matplotlib 坐标轴上。这样我们就可以控制图像大小、标题、坐标轴、图例、边距和导出效果。
import geopandas as gpd
import matplotlib.pyplot as plt
gdf = gpd.read_file("data/city_districts.shp")
fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax)
plt.show()
这段代码比直接 gdf.plot() 多了一个关键步骤:我们手动创建了 fig 和 ax。后面所有美化操作,基本都围绕这两个对象展开。
步骤:用Matplotlib调整GeoPandas地图样式
步骤1:读取数据并检查坐标系
正式绘图前,先检查数据是否能正常读取,以及坐标系是否正确。坐标系错误会导致地图变形、比例异常,甚至不同图层叠不到一起。
import geopandas as gpd
import matplotlib.pyplot as plt
gdf = gpd.read_file("data/city_districts.shp")
print(gdf.head())
print(gdf.crs)
如果是做面积、距离或城市范围专题图,建议使用合适的投影坐标系,而不是直接用经纬度坐标系。比如中国区域项目常见情况是先确认数据坐标,再根据项目范围选择合适投影。
# 示例:如果需要,可转换到已有项目指定的投影坐标系
# gdf = gdf.to_crs("EPSG:3857")
注意:不要盲目转换坐标系。真实项目中应以数据来源说明、项目规范或地方坐标标准为准。
步骤2:设置画布大小和地图比例
默认图像尺寸往往不适合展示。可以用 figsize 控制画布宽高,用 ax.set_aspect("equal") 尽量保持地图比例。
fig, ax = plt.subplots(figsize=(9, 7))
gdf.plot(
ax=ax,
color="#d9e8f5",
edgecolor="#4a4a4a",
linewidth=0.6
)
ax.set_aspect("equal")
plt.show()
这里的几个参数很常用:
color:面填充颜色;edgecolor:边界线颜色;linewidth:边界线宽度;figsize:整张图的大小。
对行政区、地块、网格等面数据来说,边界线非常重要。没有边界线时,多个面要素容易看成一整块。
步骤3:按字段做专题图配色
如果地图需要表达某个指标,比如人口、GDP、POI 数量、风险等级,就不要只用单一颜色。GeoPandas 可以通过 column 参数按字段渲染。
fig, ax = plt.subplots(figsize=(9, 7))
gdf.plot(
column="population",
ax=ax,
cmap="YlOrRd",
legend=True,
edgecolor="#ffffff",
linewidth=0.5
)
ax.set_title("各区人口分布图", fontsize=16, pad=12)
ax.set_axis_off()
plt.show()
常见配色建议:
- 连续数值:
YlOrRd、Blues、Greens; - 正负差异:
RdBu、coolwarm; - 分类数据:
Set2、tab20; - 避免过度使用彩虹色:很多时候不利于阅读。
如果你的字段是中文或分类字段,也可以直接用于分类制图,但要注意图例可能较长,需要调整位置。
步骤4:调整图例,让专题图更像正式成果
GeoPandas 的 legend=True 很方便,但默认图例不一定美观。可以通过 legend_kwds 设置图例标题、方向和缩放。
fig, ax = plt.subplots(figsize=(9, 7))
gdf.plot(
column="population",
ax=ax,
cmap="YlOrRd",
legend=True,
edgecolor="#ffffff",
linewidth=0.5,
legend_kwds={
"label": "人口数量",
"orientation": "vertical",
"shrink": 0.65
}
)
ax.set_title("各区人口分布图", fontsize=16, pad=12)
ax.set_axis_off()
plt.show()
如果图例太占地方,可以尝试:
- 增大
figsize; - 减少分类数量;
- 使用横向图例;
- 导出后在版式软件中再做精细排版;
- 对分类字段先合并过细的类别。
步骤5:去掉坐标轴、设置标题和边距
很多 GIS 专题图并不需要直接显示坐标轴。尤其是行政区分布图、统计专题图、空间分析结果图,坐标轴经常会干扰阅读。
fig, ax = plt.subplots(figsize=(9, 7))
gdf.plot(
column="population",
ax=ax,
cmap="YlOrRd",
legend=True,
edgecolor="#ffffff",
linewidth=0.5
)
ax.set_title("各区人口分布图", fontsize=16, pad=14)
ax.set_axis_off()
plt.tight_layout()
plt.show()
plt.tight_layout() 可以自动调整边距,减少标题、图例和图像之间的挤压。但在复杂地图中,它不是万能的。如果图例仍然被裁切,需要手动调整画布大小或使用 bbox_inches="tight" 导出。
步骤6:处理中文字体乱码
如果 Matplotlib 中的中文标题显示为方框,说明当前环境没有正确设置中文字体。可以在脚本开头指定字体。
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
如果你使用的是 macOS 或 Linux,SimHei 不一定存在。可以改成系统中已有的中文字体。例如:
# macOS 常见可尝试字体
plt.rcParams["font.sans-serif"] = ["Arial Unicode MS"]
# Linux 服务器常见做法是先安装中文字体,再指定字体名称
在 Jupyter Notebook 中,如果改了字体仍不生效,可以重启 Kernel 后再运行。
步骤7:叠加边界、点位和标注
实际 GIS 出图常常不是单图层。比如底图是区县面,叠加采样点、站点或道路。可以多次调用 plot(),画到同一个 ax 上。
districts = gpd.read_file("data/city_districts.shp")
stations = gpd.read_file("data/stations.geojson")
stations = stations.to_crs(districts.crs)
fig, ax = plt.subplots(figsize=(9, 7))
districts.plot(
ax=ax,
color="#f2f2f2",
edgecolor="#666666",
linewidth=0.6
)
stations.plot(
ax=ax,
color="#d7191c",
markersize=28,
alpha=0.85
)
ax.set_title("监测站点空间分布图", fontsize=16, pad=12)
ax.set_axis_off()
plt.tight_layout()
plt.show()
多图层叠加时,最常见的问题是坐标系不一致。因此每次叠加前都建议检查:
print(districts.crs)
print(stations.crs)
如果坐标系不同,应使用 to_crs() 转成同一个坐标系。
步骤8:导出高清图片
很多人觉得 GeoPandas 绘图太丑,其实还有一个原因是导出图片分辨率太低。正式使用时,不建议直接截图,而应该用 savefig() 导出。
fig, ax = plt.subplots(figsize=(9, 7))
gdf.plot(
column="population",
ax=ax,
cmap="YlOrRd",
legend=True,
edgecolor="#ffffff",
linewidth=0.5,
legend_kwds={
"label": "人口数量",
"shrink": 0.65
}
)
ax.set_title("各区人口分布图", fontsize=16, pad=12)
ax.set_axis_off()
plt.savefig(
"output/population_map.png",
dpi=300,
bbox_inches="tight",
facecolor="white"
)
plt.show()
导出参数建议:
dpi=300:适合报告、论文和打印;bbox_inches="tight":减少白边并避免图例被裁切;facecolor="white":避免透明背景在文档里变黑;png:适合常规位图输出;svg或pdf:适合矢量编辑和出版排版。
常见坑:GeoPandas绘图不好看的原因不只一个
坑1:字段类型不对,导致专题图颜色异常
如果用于制图的字段看起来是数字,但实际是字符串,颜色分级可能不符合预期。可以先检查字段类型。
print(gdf["population"].dtype)
必要时转换为数值:
gdf["population"] = gdf["population"].astype(float)
坑2:空值没有处理,地图出现缺块
专题字段里有空值时,部分区域可能不着色。可以先统计空值数量。
print(gdf["population"].isna().sum())
如果空值有业务含义,建议单独设置缺失值样式,而不是简单删除。
gdf.plot(
column="population",
cmap="YlOrRd",
legend=True,
missing_kwds={
"color": "lightgrey",
"edgecolor": "white",
"hatch": "///",
"label": "缺失值"
}
)
坑3:坐标系不一致,叠加图层错位
点、线、面叠加时,如果一个图层是 EPSG:4326,另一个图层是投影坐标系,就会出现错位或看不到图层的问题。
points = points.to_crs(polygons.crs)
注意:to_crs() 的前提是原始 CRS 已经正确。如果数据本身没有 CRS,需要先确认真实坐标系,再使用 set_crs() 定义。
坑4:图例被裁切或挤压
图例被裁切通常和画布大小、图例位置、导出边界有关。优先尝试:
- 增大
figsize; - 使用
bbox_inches="tight"; - 减少图例分类;
- 调整
legend_kwds中的shrink; - 将图例改成横向。
坑5:边界线太粗,地图显得很脏
面要素数量很多时,边界线过粗会让地图显得混乱。可以降低线宽,或只显示上一级行政边界。
gdf.plot(
column="value",
cmap="Blues",
edgecolor="white",
linewidth=0.2
)
坑6:默认分类不符合 GIS 专题图表达
GeoPandas 默认连续渲染不一定适合所有指标。如果要做分级设色图,可以结合 scheme 参数使用分类方法。该功能通常依赖 mapclassify。
gdf.plot(
column="population",
cmap="YlOrRd",
scheme="Quantiles",
k=5,
legend=True,
edgecolor="white",
linewidth=0.4
)
常见分级方式包括:
- Quantiles:分位数,每一类数量接近;
- EqualInterval:等间距,便于解释;
- NaturalBreaks:自然断点,适合数据聚类明显的情况。
方法比较:GeoPandas、Matplotlib、QGIS该怎么选
| 方法 | 适合场景 | 优点 | 局限 |
|---|---|---|---|
| GeoPandas 默认 plot | 快速检查数据、调试空间处理结果 | 代码少,出图快 | 默认样式简单,不适合正式制图 |
| GeoPandas + Matplotlib | Python 自动化制图、批量专题图、分析报告 | 可重复、可批量、样式可控 | 复杂排版需要写较多代码 |
| QGIS 布局管理器 | 正式地图版式、比例尺、指北针、图框制图 | 制图元素完整,交互式调整方便 | 批量自动化需要额外配置或脚本 |
| ArcGIS Pro 布局 | 规范制图、企业项目、地图册输出 | 专业制图能力强,布局工具成熟 | 软件授权和环境成本较高 |
如果你只是想快速看一下数据,GeoPandas 默认绘图就够了。如果你要把 Python GIS 分析结果自动生成多张图,GeoPandas 加 Matplotlib 更合适。如果你要做标准地图成果,包括比例尺、指北针、图框、坐标网,QGIS 或 ArcGIS Pro 的布局工具会更省心。
检查清单:调整GeoPandas地图前先看这几项
- 是否确认了数据 CRS,不同图层是否已经统一坐标系?
- 专题字段是否为正确的数据类型?
- 是否处理了空值、异常值和极端值?
- 配色是否符合数据类型:连续、分类、正负差异?
- 面边界线是否过粗或过细?
- 是否去掉了不必要的坐标轴?
- 标题、图例、单位是否完整?
- 中文字体是否正常显示?
- 导出时是否设置了
dpi和bbox_inches? - 最终图片是否在 Word、PPT、网页或论文模板中实际检查过?
FAQ:GeoPandas绘图太丑的常见问题
GeoPandas绘图太丑,是不是不适合做地图?
不是。GeoPandas 更偏向空间数据分析和自动化处理,默认绘图只是快速预览。只要结合 Matplotlib 调整配色、图例、边界和导出参数,完全可以做出清晰的专题图。但如果需要比例尺、指北针、图框和复杂版式,建议再用 QGIS 或 ArcGIS Pro 完成最终排版。
Matplotlib怎么调整GeoPandas地图颜色?
最常用的是在 gdf.plot() 中设置 color、column 和 cmap。单色地图用 color,专题图用 column 指定字段,再用 cmap 指定色带。
gdf.plot(column="value", cmap="Blues", legend=True)
GeoPandas地图怎么去掉坐标轴?
使用 Matplotlib 的 ax.set_axis_off() 即可。通常行政区专题图、点位分布图和报告插图都可以去掉坐标轴,让画面更简洁。
fig, ax = plt.subplots(figsize=(8, 6))
gdf.plot(ax=ax)
ax.set_axis_off()
GeoPandas图例太丑怎么调?
可以使用 legend_kwds 调整图例标题、方向和缩放。例如:
gdf.plot(
column="value",
legend=True,
legend_kwds={
"label": "指标值",
"orientation": "vertical",
"shrink": 0.7
}
)
如果是复杂分类图,建议先减少类别数量,或者把图例放到导出后的版式中单独处理。
GeoPandas导出的图片为什么很糊?
通常是因为直接截图,或者 savefig() 没有设置足够的 dpi。建议使用:
plt.savefig("map.png", dpi=300, bbox_inches="tight", facecolor="white")
如果后续还要在 Illustrator、Inkscape 或论文模板中编辑,可以导出 SVG 或 PDF。
GeoPandas中文标题乱码怎么办?
需要设置 Matplotlib 中文字体。Windows 环境可尝试:
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
如果字体不存在,需要换成系统已安装的中文字体,或者先安装中文字体。
GeoPandas能不能加比例尺和指北针?
可以,但 GeoPandas 和 Matplotlib 并不像 QGIS 布局管理器那样内置完整地图制图元素。简单比例尺、指北针可以用 Matplotlib 手工绘制或借助扩展库实现;如果是正式地图成果,建议使用 QGIS 或 ArcGIS Pro 做最终制图。
结论:GeoPandas负责空间数据,Matplotlib负责图面表达
遇到 GeoPandas 绘图太丑,不要只停留在 gdf.plot() 这一层。正确做法是:先用 GeoPandas 读取、处理和渲染空间数据,再用 Matplotlib 控制画布、标题、图例、坐标轴、字体和导出质量。
一个实用的工作流是:检查 CRS,选择专题字段,设置配色和边界,关闭无用坐标轴,处理中文字体,最后用 savefig() 导出高清图片。掌握这套流程后,GeoPandas 绘图不仅能用于数据检查,也能稳定产出适合 GIS 作业、分析报告和 Web 文章配图的专题地图。