简介:面向GIS开发者、地理信息研究人员及相关专业学习者,该资源提供全国尺度地貌分布矢量图层,数据采用shapefile格式,附带地貌代码与地貌类型字段,可满足地貌分类查询、空间分析与专题制图等常见需求,适合用于区域规划、地质研究及教学演示场景。压缩包内共10个文件,以shp主文件为核心,配套dbf属性表、prj投影信息、shx几何索引及sbn/sbx空间索引,mxd工程文件可直接在ArcGIS中打开,xml与doc则包含元数据和使用说明,整体仅6.17MB,轻量易用。已有396人学习下载,说明该数据在相关领域具有一定参考价值。通过学习该资源,用户可快速获取全国统一标准的地貌分布矢量底图,无需自行采集与规范化处理;基于属性表中的地貌代码可进行多级分类筛选,结合Python或GIS工具完成批量统计与可视化输出,适合作为专业分析的基础数据图层,亦可帮助初学者掌握shp文件结构及其配套文件的组织方式。
1. 全国地貌分布 shp 矢量图层:拿到手就能用的边界数据与出图思路
做 GIS 的人应该都有过这种经历:手里攒了一堆 POI、气象站点、采样点数据,想按地貌类型做个分区统计,结果翻遍全网找不到一套干净、完整、带属性表的全国地貌矢量边界。有些公开数据是栅格,转矢量要装 GDAL,还得自己清洗边缘;有些是分省分块下载,拼完以后相邻图幅之间接缝对不上,拓扑错误一堆。这套全国地貌分布 shp 矢量图层数据,最直接的用处就是把「按地貌分区」这件事从数据处理里解放出来——你拿到的是一份已经合并好的多边形图层,属性表里带地貌类型字段,直接用 Python 的 geopandas 读取、按字段分组统计、叠加分析,或者丢进 ArcGIS Pro 做制图综合都可以。适合做科研绘图、规划前期分析、国土空间相关课程设计,以及需要全国尺度地貌底图的各类项目。文件是标准 shp 三件套加属性表,坐标系是地理坐标 WGS84,不涉及投影参数,入手先看边界对不对,再谈别的。
2. 认识这份数据的结构:字段设计、坐标系与边界细节
2.1 属性字段与地类划分逻辑
拿到 shp 压缩包,解压后建议先不要直接拖进 ArcGIS,先看一眼.dbf的属性结构。用 Python 打开最稳,因为.dbf里字段名如果是中文,在 ArcMap 老版本里会出现乱码,而在 geopandas 里只要encoding指定对,一般能直接读出来。常见做法是:
import geopandas as gpd gdf = gpd.read_file("全国地貌分布.shp", encoding="utf-8") print(gdf.columns.tolist()) print(gdf.head())字段一般包含地貌类型名称、类型代码、面积或周长这类基础属性。如果你看到类似TYPE、CODE、AREA这样的英文字段名,那大概率是为了兼容老式 GIS 软件做的规范处理。地貌分类体系通常参考《中国地貌图》的划分逻辑,大类下有平原、丘陵、山地、高原等,细分会有像喀斯特地貌、黄土地貌、火山地貌这类特殊类型。拿到手第一步要做的不是直接出图,而是先跑一下value_counts()看类型的数量和名称,确认分类粒度是不是你项目需要的:
# 统计各地貌类型要素数量 counts = gdf["TYPE"].value_counts() print(counts.head(20))这一步的意义在于:如果你的目标是做全国宏观地貌分区图,那大类就够了;如果你要分析某个流域内的小地貌组合,那可能需要按细分类型筛选。属性表里如果「类型」字段存在多级分类,比如一个字段存的是大类、另一个字段存的是亚类,那实际使用时应优先用最细粒度做分析,最后制图时再按大类合并,这样后期如果需要反悔,不用回炉重做。
2.2 坐标系、范围与边界情况
这套数据是 WGS84 地理坐标系,也就是说所有多边形节点都是经纬度坐标。在全国尺度上看,用 Albers 等积投影来做面积统计是更稳妥的,因为 WGS84 经纬度坐标下直接算面积,单位是度,完全没法用。做分区统计前,建议先把数据投影到适合中国范围的 Albers 投影,参数一般是中央经线 105°E,双标准纬线 25°N 和 47°N。Python 里一步到位:
gdf_proj = gdf.to_crs("+proj=aea +lat_0=0 +lon_0=105 +lat_1=25 +lat_2=47 +datum=WGS84") gdf_proj["面积_km2"] = gdf_proj.geometry.area / 1e6注意,这里的geometry.area返回的是投影坐标系下的面积,单位是平方米,除以 1e6 得到平方公里。投影完了再做dissolve或者overlay,能避免很多因坐标系混乱导致的空间分析结果异常。这个步骤几乎是所有全国尺度分析里必走的流程,不要省略。
2.3 边界完整性检查:岛屿、国界与碎裂多边形
任何全国尺度的 shp 数据,拿到手都得做一次边界完整性和拓扑检查。重点看三块:南海诸岛有没有单独的小要素;西北边界是否存在未闭合的多边形;大面积连片地貌中是否散落着极其细碎的碎块。这种碎块通常来自原始数据切图边界,或者是相邻图幅拼接时产生的伪多边形。
# 检查面积过小的要素,疑似碎块 gdf_proj["面积"] = gdf_proj.geometry.area / 1e6 small = gdf_proj[gdf_proj["面积"] < 0.5] print(small.shape)如果碎块数量不大,建议直接用面积阈值过滤掉,因为这种碎块在图面上会让填充符号产生视觉噪声,拉低制图质量。如果碎块数量很大,可能这套数据的精度本来就比较碎,那就要考虑先做dissolve合并同类型,再过滤小面积多边形。我一般会把dissolve放在过滤之后,这样每个类型只剩一个或几个大面,边界也整齐,后面不管做专题图还是做叠加分析都更稳。
3. 用 Python + geopandas 读取、筛选和出图
3.1 读取数据与字段清洗
如果你已经安装了 geopandas,读取这套 shp 数据非常简单,但要注意.dbf编码。国内很多公开数据的属性表是 GBK 编码,如果直接读出来中文乱码,需要指定encoding="gbk"。判断方法很直接:先读取一次看字段名和值,乱码就换编码。另外,字段前后可能带空格,这种情况用strip()处理字段名即可。
import geopandas as gpd import matplotlib.pyplot as plt # 读取,按需切换编码 gdf = gpd.read_file("全国地貌分布.shp", encoding="utf-8") # 统一去掉字段名的首尾空格 gdf.columns = [col.strip() for col in gdf.columns] print(gdf.head())我建议在项目开始前先列一个字段说明表,记录每个字段存的是什么,这样后期交接给同事或者自己两个月后再回来看,不用重新猜字段含义。特别是如果给课程设计或毕业论文用,数据集自带的字段命名不透明,写个字段字典能省很多时间。
3.2 按区域裁剪与叠加分析实践
最常见的实际场景是拿到了全国地貌图,但我只用其中一个省或一个流域。这时候要用到的是裁剪或空间连接。比如你有云南省的行政区边界,想裁剪出云南的地貌分布图。用 geopandas 的clip函数效率很高,前提是两个图层坐标系一致,不一致先to_crs统一。
from geopandas.tools import clip # 读取行政区边界 province = gpd.read_file("云南省界.shp", encoding="utf-8") province = province.to_crs(gdf.crs) # 裁剪全国地貌矢量 gdf_yunnan = clip(gdf, province) print(gdf_yunnan["TYPE"].value_counts())这一步的关键是province本身不能有拓扑错误,否则裁剪结果会出现裂缝。如果裁剪后某些多边形边缘不贴合,常见的做法是给边界做一个 0.01 度的缓冲区,然后裁剪后再擦除缓冲区,这样边缘能闭合得更好。不过这套地貌数据的精度如果本身不高,边缘重合一两公里都很正常,不需要为小缝太过纠结。
3.3 地图可视化与出图参数
可视化这块,用 matplotlib 做快速预览够用了,但输出正式图件建议还是把数据导出后丢进 QGIS 或 ArcGIS 调符号。预览阶段的关键是不要一张图把所有类型都塞进去,否则小地类在图面上完全看不清。我一般先做合并,把面积占比极小的类型归并到「其他」,再按分类数量选颜色方案。
# 把面积占比小于0.5%的类型归并为“其他” total_area = gdf_proj["面积"].sum() gdf_proj["大类"] = gdf_proj["TYPE"].where(gdf_proj["面积"] > total_area * 0.005, "其他") fig, ax = plt.subplots(figsize=(10, 8)) gdf_proj.plot(column="大类", cmap="Spectral", legend=True, ax=ax, edgecolor="none") ax.set_axis_off() plt.savefig("地貌分布预览.png", dpi=300, bbox_inches="tight")这里注意cmap="Spectral"适合连续渐变地类,但如果是定性分类数据,用tab20或Set3这类定性调色板更合适。edgecolor="none"一定要设,否则碎小多边形之间会有一堆黑色细线,图面脏乱。出图前建议先dissolve一次,把同类型边界合并掉,效果会好很多。
4. 实战中常见的坑:边界、编码、坐标系与拓扑问题
4.1 属性表中文乱码
现象:在 ArcMap 里打开属性表,地貌类型字段全是「锟斤拷」一类乱码,但图形显示正常。
原因:shp 文件的.dbf属性表编码是 GBK,而 ArcMap 默认按系统语言读取,在某些版本或某些数据来源下会误判为 UTF-8。
解决:推荐直接用 QGIS 打开,加载时选择 编码 GBK;或者用 Python 的 geopandas 指定encoding="gbk"重新读取,再另存为 UTF-8 编码的新 shp。另存的时候建议顺便把字段名统一改成英文或拼音,避免后续跨平台出问题。
4.2 拼接缝与轻微偏移
现象:从全国图中裁出某个区域后,发现地貌多边形与自己的采样点或野外调查边界差了约 1 公里。
原因:这套数据源头坐标精度大概在 1:100 万级别,边缘不保证像素级精确。如果叠合的是更高精度的 GPS 实测数据,就会出现非系统性偏移。
解决:判断偏移到底是数据精度还是坐标系不同导致的。先确保两边都是 WGS84 经纬度,然后用几个特征点(如山峰、大型水体边界)做目视比对。如果是整体偏移,按固定向量平移即可;如果是精度不够,不要试图强行纠正,直接按数据来源在论文或报告中标注精度即可。
4.3 小碎块要素过多
现象:按类型做专题图后,图面上出现大量红色或紫色小点,主要是山地或丘陵类型的细小面。
原因:原始地貌图在拼接或栅格转矢量过程中,会残留大量面积小于几平方公里的碎块,这些碎块在制图时影响美观。
解决:在分析前先按面积阈值过滤,比如仅保留面积大于 10 平方千米的要素。阈值怎么定看你的目标尺度和出图比例尺。如果做的是全国图,建议过滤掉所有小于 50 平方千米的碎面;做省级图可以放宽到 5 平方千米。用geopandas一句gdf = gdf[gdf.area > threshold]就能完成。
4.4 边界数据包含九段线但缺少岛屿
现象:全国范围看起来没问题,但仔细核对发现南海诸岛缺少部分岛礁矢量,或者台湾岛要素存在但边界精度较粗。
原因:公共数据源的常见裁剪策略,部分岛屿要素在低精度版本中被简化掉,或者原始数据本身就不包含碎岛。
解决:如果是制图需求,使用国家测绘部门发布的标准审图号底图叠加补充;如果是分析需求,补充岛屿影响面积占比通常可忽略不计,但需在方法部分写清数据来源与精度。
4.5 拓扑错误导致面积计算异常
现象:用dissolve合并同类型后,有的多边形出现「负面积」或者geometry.is_valid返回False。
原因:矢量数据存在自相交、重叠环或空隙,常见于拼接数据。
解决:在每次空间操作前统一执行gdf = gdf.buffer(0),这个方法能消除大多数自相交问题,同时尽量保留原边界形状。如果仍然无效,再用gpd.make_valid()修复,但有可能会产生极少量的多边形几何变化,需要留意。
5. 进阶用法:多源数据叠加、分类重映射与成果输出
5.1 地貌类型与降水、植被数据叠加分析
把地貌矢量当成一个基础分区单元,可以叠加气候或遥感数据做统计分析。比如你想知道每类地貌多年平均降水量分布区间,先用地貌图做分区,然后提取各分区内栅格像元均值。两种实现路径:一个是在 Python 里用rasterstats包,另一个是在 ArcGIS 里用 Zonal Statistics as Table。推荐前者,因为语法干净且不依赖 GUI。
from rasterstats import zonal_stats stats = zonal_stats( "全国地貌分布.shp", "降水_2000_2020_年均.tif", stats=["mean", "std", "count"], prefix="precip_", )zonal_stats要求矢量与栅格坐标系一致,不一致时用affine和crs参数处理。这里的prefix参数很实用,输出字段会自动带上前缀,避免多个栅格叠加时字段名冲突。注意zonal_stats的返回值是列表,每个元素对应矢量层的一条要素,和 geopandas 合并时保持顺序一致即可。
5.2 按自定义标准重分类与合并类型
如果不满意原数据的分类粒度,可以用属性字段做条件映射。比如把「喀斯特地貌」和「黄土地貌」归入「特殊地貌」,把几类山地合并为「山地」大类。这种操作在制图时常被需要,可能也与你论文的指标体系直接相关。
def reclassify(row): t = row["TYPE"] if t in ["喀斯特地貌", "黄土地貌", "火山地貌"]: return "特殊地貌" elif "山地" in t: return "山地" elif "平原" in t: return "平原" else: return "其他" gdf["类型组"] = gdf.apply(reclassify, axis=1) gdf_dissolved = gdf.dissolve(by="类型组", aggfunc="sum")dissolve是这一步的核心操作,aggfunc="sum"会把同组要素的属性字段求和,这样合并后还能保留面积总量等信息。重分类的规则建议写在脚本开头,作为可配置的字典,方便后续统一调整。特别注意:字段值里包含「高原」「盆地」这些词时,用in判断可能误伤,所以更严谨的做法是维护一个白名单。
5.3 导出为 GeoJSON、TopoJSON 或 KML
数据落地还有一种常见需求:把地貌矢量转成 GeoJSON,丢到 Leaflet 或 Mapbox 上做 Web 可视化。geopandas 一句话搞定:
gdf.to_file("地貌分布.geojson", driver="GeoJSON")如果是做地图加载性能优化,可以转 TopoJSON,文件体积能缩小一半以上。转 KML 则直接用driver="KML",但注意 KML 对字段类型有限制,有些字段会丢失。以我的习惯,交付给前端同事我会给 GeoJSON;交给甲方或非专业同事我会顺便导出一份带图例的 PDF。因为很多甲方拿到的数据不一定会用 GIS 软件打开,导出一个 PDF 预览给三方软件看图,是最不容易出错的交付方式。
5.4 数据预处理完整工作流参考
我把上面提到的步骤整合成一套相对通用的预处理流程。代码包括读取、投影、过滤、修复、导出五段,每一段都用注释标注了调整入口。这套流程可以直接照抄作为你的项目起点,再按实际需求删减环节。就以这套流程跑一次,能保证数据质量底线。换台电脑、换份数据,只要能读到文件,流程复用度很高,唯一要做的是把字段名和阈值改掉。从那以后我每次拿到新的 shp 底图数据,都强制自己先过一遍这套流程,再进分析环节,省掉了无数后期返工。希望帮到你。
本文还有配套的精品资源,点击获取