简介:这套数据是昆明市乡镇街道级行政区划矢量文件,包含昆明各区县的shp图层,面向GIS开发、城乡规划、地理信息分析等用户,用于地图制图、边界确认及空间统计。压缩包内共22个文件,以shp矢量格式为主,配套shx几何索引、dbf属性表、prj投影文件、sbn/sbx空间索引、xml元数据及一张jpg预览图,可在ArcGIS、QGIS等平台直接加载使用。整个rar压缩包仅402KB,体量精简,便于分发和存储。数据覆盖昆明市及下辖区县的乡镇街道边界,属性字段与坐标参考均以文件方式整理齐全,拿到后即可开展制图与空间分析,无需再耗费精力在网络上零散寻找原始底图。当前已有860人学习/下载;如使用中遇到数据兼容性问题,作者提供后续协助处理,是相关论文与项目制作地理底图的实用选择。
1. 昆明各乡镇街道 shp:叠图之前先验收边界数据
做论文图件或者规划底图时,最耽误进度的不是制图本身,而是找一套能直接用的昆明乡镇街道边界数据。翻遍各类 GIS 论坛和分享群,下载到的往往只有昆明市级简化边界,或者带水印、缺投影文件的半成品,贴到 ArcMap 里和道路、POI 数据根本套不齐。行政区划边界这种数据不像 2020 全国道路 shp 下载那样流通量大、到处都有,乡镇街道级别属于低频数据,搜一次经常搭进去半天。
这套资源包给的是可以直接用的昆明各乡镇街道 shp 矢量文件,同时附带了昆明各区县 shp,相当于市级、区县级、乡镇街道级三层边界一次拿齐。文件族完整,.shp 几何、.dbf 属性、.prj 投影、.sbn/.sbx 空间索引都在,不用自己补后缀。适合做论文附图、规划底图、网点落点和空间统计的 GIS 从业者和相关专业的学生。下面按 shapefile 文件结构、加载查询、经纬度落点、边界修复这条线往下走,每一步都给可复现的命令和代码。
2. 拆解昆明各乡镇街道 shp 文件族:shp/shx/dbf/prj/sbn/sbx 各管什么
2.1 完整的 shapefile 是一组文件,不是一个文件
解压压缩包后,会看到以同一主文件名开头的一批后缀,这是 shapefile 格式的固有存储方式:几何坐标、属性表、索引分别放在不同文件里。很多人只把 .shp 单文件拷走,换台电脑再打开就报错,正是因为这个原因。所谓 eps 地图转为 shp、dwg 转换 shp 这类格式转换,最后生成的同样是这一组文件族,理解了结构,排查问题才有方向。
这套资源里文件族的职责如下表:
| 后缀 | 存放内容 | 缺失时的影响 |
|---|---|---|
| .shp | 要素几何坐标(点、线、面本体) | 图层无法加载 |
| .shx | 几何位置索引 | 多数软件可重建,但部分工具读取报错 |
| .dbf | 属性字段(名称、编码、面积等) | 图层无属性表,无法做字段筛选 |
| .prj | 坐标系描述文本 | 以未知坐标系加载,叠加错位 |
| .sbn / .sbx | ArcGIS 生成的空间索引 | 不影响显示与编辑,仅影响查询效率 |
| .shp.xml | 元数据描述 | 可选择性保留,不影响使用 |
拿到任何 shp 数据的第一件事,就是按这张表核对后缀是否齐全。尤其要确认 .dbf 和 .prj 在不在。包里同时有昆明各乡镇街道命名的一套和昆明各区县命名的一套,两套文件族同源,加载时注意按文件名区分层级,别把区县边界当成街道边界叠进去。
2.2 prj 决定坐标系:先验投影,再谈叠加
行政区划数据常见的坐标系有三种:WGS84 地理坐标(EPSG:4326)、CGCS2000 地理坐标(EPSG:4490)以及经过高斯克里格投影的平面坐标(分带不同 EPSG 编号不同)。昆明所在的区域涉及三度分带和六度分带的差异,叠加之前必须先读 prj 文件确认坐标系,否则两个图层错位几百米是常态。
GDAL 装好后,用命令行最快完成验证:
ogrinfo -ro -so 昆明各乡镇街道.shp 昆明各乡镇街道 | grep -E "EXTENT|PROJCS|GEOGCS|EPSG"EXTENT: (102.4xxxx, 24.4xxxx) - (103.4xxxx, 26.1xxxx) GEOGCS["GCS_WGS_1984"]参数说明:-ro是只读模式,-so是 summary-only 只输出概要,不遍历要素;grep过滤出范围、投影和基准信息。若 EXTENT 是两位小数的经纬度值,说明是地理坐标;若是六位数的米制值,说明是投影坐标。Windows 环境没有 grep 时,直接不接管道跑ogrinfo -ro -so看全部输出即可。
昆明资料的 prj 里如果出现CGCS2000_3_Degree_GK_CM_102E这类描述,表示 CGCS2000 三度分带、中央经线 102°E 的高斯投影,这类数据在跨图层叠加前最好统一坐标。把多个图层统一到 CGCS2000 地理坐标的常见做法:
ogr2ogr -t_srs EPSG:4490 昆明乡镇4490.shp 昆明各乡镇街道.shp ogr2ogr -t_srs EPSG:4490 昆明区县4490.shp 昆明各区县.shp-t_srs EPSG:4490指定目标坐标系,输出文件另存为新的文件族,不覆盖原始数据;想强制覆盖同名输出时加-overwrite。统一后再叠加其他来源的道路、水系图层,错位问题一般都能消除。
2.3 用 pyshp 检查 dbf 字段,理解 sbn/sbx 的作用
.dbf 是早期 dBASE 表结构,字段名最长 10 个字符,中文属性在不同编码环境下容易乱码。做任何字段操作前,先用 Python 的 pyshp 把属性结构读出来:
import shapefile sf = shapefile.Reader("昆明各乡镇街道.shp", encoding="utf-8") print("要素数量:", len(sf)) print("字段定义:") for f in sf.fields: print(" ", f) print("前 3 条记录:") for rec in sf.records()[:3]: print(" ", rec) sf.close()逻辑说明:Reader 读取整个文件族,fields返回字段定义列表,每条记录是一个与字段顺序对应的元组。打印中文乱码时,把 encoding 依次换成"gbk"再试,街道名称这类属性大多以国标编码保存。常见字段一般包含名称、行政区划代码、面积、周长等,具体以包里 dbf 实测为准,不要凭记忆写字段名。
.sbn 和 .sbx 是 ArcGIS 生成的空间索引,QGIS 打开图层时不会读它们,删除也不影响图形和属性。如果你的工作流里频繁做相交、叠加查询,建议保留这两个文件,在 ArcGIS 环境中查询会更快。QGIS 用户不必依赖它,在图层属性里重新建立空间索引效果相同。
提示:加载任何 shp 前,先跑一遍
ogrinfo -ro -al -so 昆明各乡镇街道.shp,看到正确的要素计数和坐标范围,再把数据放进工程,能省掉后续一大半排查时间。
3. QGIS 与 ArcMap 加载昆明乡镇街道数据:属性查询与空间统计
3.1 加载图层并核对要素数与坐标系
QGIS 里加载 shp 最直接的方式是把 .shp 拖进图层窗口,软件会按文件族自动识别其余配套文件;也可以走图层菜单的添加矢量图层,编码乱码时在 UTF-8 和 GBK 之间切换。ArcMap 里用添加数据按钮,在 Catalog 窗口里选中 .shp 即可,不需要逐个添加伴生文件。
加载后第一件事是核对要素数量和坐标系。QGIS 的 Python 控制台执行:
layer = QgsProject.instance().mapLayersByName("昆明各乡镇街道")[0] print("要素个数:", layer.featureCount()) print("字段数:", len(layer.fields())) print("坐标系:", layer.crs().authid())代码说明:mapLayersByName按图层名取到 QgsVectorLayer 对象,featureCount()统计要素数量,fields()列出字段集合,crs().authid()返回坐标系 EPSG 编号。如果要素数量与 dbf 记录数不一致,说明几何文件与属性表错位,这类数据直接弃用,不值得花时间修。
还需要做一次目视叠加检查:把昆明各乡镇街道和昆明各区县两层同时打开,确认街道边界与区县边界完全套合。如果层间有明显缝隙,优先检查是不是坐标系没统一,而不是怀疑数据坏了。
3.2 属性筛选:按区县名或代码提取街道要素
做专题图时经常要提取某个区县下的街道。在 QGIS 属性表里用表达式选择,例如只保留五华区的街道:
"NAME" LIKE '%五华%'left("CODE", 4) = '5301'逻辑说明:第一条用LIKE配合%通配符做名称模糊匹配,字段名以实际 dbf 为准;第二条用left()截取行政区划代码前四位做精确前缀匹配,街道级代码是十二位,区县级代码是前四位。两条都适用时就优先用代码匹配,名称匹配容易把「五华」误伤到其他字段。
筛选结果可以右键图层导出为新图层,格式选 ESRI Shapefile,坐标系建议保持原始不动,避免在导出环节再引入一次转换。若是给 Web 项目用,导出 GeoJSON 更合适,字段名建议先改成英文再导出,中文字段名在部分前端解析库里有兼容问题。
3.3 邻接判断与椭球面积统计
行政区划分析里最常见的需求是邻接判断:如某个街道与哪些乡镇街道接壤。批量场景下 PyQGIS 循环更可控:
layer = QgsProject.instance().mapLayersByName("昆明各区县")[0] features = {f["NAME"]: f for f in layer.getFeatures()} target_name = "五华区" target_geom = features[target_name].geometry() neighbors = [] for name, f in features.items(): if name == target_name: continue if target_geom.intersects(f.geometry()): neighbors.append(name) print("与", target_name, "接壤的区县:", neighbors)代码说明:先把要素按名称字段缓存成字典,取目标区县几何,遍历其他要素逐个intersects()。相邻区县理论上共享边界线,若数据存在缝隙,intersects()返回 False,会漏掉真实邻居,此时需要先做第 5 章的拓扑修复。intersects()是空间关系判断,性能取决于要素数量,区县级几十个要素直接遍历完全没问题,街道级几百个要素也没压力。
面积统计要注意单位问题。直接在投影坐标系下用geometry().area()得到的是平面面积,不同分带和投影标准下误差不同。论文级数据建议用椭球面积:
from qgis.core import QgsDistanceArea d = QgsDistanceArea() d.setEllipsoid("WGS84") for f in layer.getFeatures(): area = d.measureArea(f.geometry()) print(f["NAME"], f"{area / 1e6:.2f} 平方千米")说明:QgsDistanceArea指定椭球体后按椭球模型计算,结果比平面坐标直接算更接近真实值。除以1e6是把平方米换成平方千米,保留两位小数。街道这种尺度平面与椭球差异不大,但全昆明市总面积要写进论文时,务必用椭球算法并在图注里写明面积计算方法。
4. 把 Excel 经纬度导入 ArcMap,与昆明区县 shp 做空间关联
4.1 预处理经纬度表:格式与坐标基准对齐
做网点落点分析时,手头常是一份 Excel,每行是网点名称、经度、纬度。要把这些点落到昆明各区县边界上,第一步是把表整理成规范结构:表头用lon、lat这类英文名,经度在前、纬度在后,数值用小数,不带度分秒符号,不带 N/E 后缀。字段名过杂时先清掉空格和特殊字符,ArcMap 对中文表头和特殊符号支持不佳。
坐标基准必须和昆明各区县 shp 一致。边界是 WGS84 或 CGCS2000 地理坐标时,Excel 经纬度可直接使用;边界是投影坐标时,需要先把点的经纬度用反向投影转成投影坐标再导入。整理后的数据表格式:
| lon | lat | name | address |
|---|---|---|---|
| 102.7187 | 25.0439 | 示例网点 | 昆明市某区某路 |
表里经纬度精度至少要保留四位小数,两位小数的经纬度误差约 1 公里,会把点判到隔壁区县。从 GPS 设备或地图 API 取数时,尽量保留原始精度,后续落点归属才可靠。
4.2 ArcMap 添加 XY 数据并导出为 shp
ArcMap 里执行「文件 > 添加数据 > 添加 XY 数据」,选择预处理好的工作表,X 字段指定 lon,Y 字段指定 lat,坐标系选择与实际基准一致。执行后生成的临时点事件图层不能直接参与空间分析,必须右键选择「数据 > 导出数据」,保存成真正的 shapefile。
这一步里坐标系选错是最常见错误。Excel 里的经纬度一般是 WGS84,而工程里的昆明区县边界可能是 CGCS2000 地理坐标,两者在昆明地区差异很小,但如果边界是投影坐标且选错基准,点位会整体偏移。稳妥做法是先确认边界坐标系,再决定点的坐标系,两个图层统一后再做分析。
QGIS 对应操作是「图层 > 添加图层 > 添加分隔文本图层」,文件编码选 UTF-8,几何定义里指定 X 字段和 Y 字段,加载后直接就是可查询的矢量点层,不需要额外导出环节。
4.3 点面包含判断:把街道名称写回原始表
点位落好后,最常用的是判断每个点落在哪个区县或乡镇街道。ArcMap 的做法是空间连接:右键点图层选「连接和关联 > 连接」,选基于空间位置的连接,目标选昆明各乡镇街道 shp,匹配规则用「每个点取其所在的面」。生成的新图层属性里带着街道名称,再导出成 Excel 就是带行政归属的网点表。
用 PyQGIS 实现同样逻辑,配合空间索引的写法在大数据量下优势明显:
point_layer = QgsProject.instance().mapLayersByName("网点points")[0] poly_layer = QgsProject.instance().mapLayersByName("昆明各乡镇街道")[0] index = QgsSpatialIndex() for f in poly_layer.getFeatures(): index.insertFeature(f) results = [] for p in point_layer.getFeatures(): ids = index.intersects(p.geometry().boundingBox()) hit = None for fid in ids: cand = poly_layer.getFeature(fid) if p.geometry().within(cand.geometry()): hit = cand break results.append((p["name"], hit["NAME"] if hit else None)) for r in results: print(r)逻辑说明:先为面图层构建 R 树空间索引,intersects(boundingBox)用点的包围盒粗筛出候选要素,再对候选逐个within()精判,两层过滤把点面匹配的计算量降了一个数量级。几万行 Excel 落点用这个写法在普通笔记本上几十秒跑完。
落点正好压在区县边界线上时,within()会返回 False,稳妥做法是给点做微小平移或先对大半个面做小缓冲。最终结果写成 CSV 交付:
import csv with open("落点归属.csv", "w", newline="", encoding="utf-8-sig") as f: w = csv.writer(f) w.writerow(["name", "street"]) w.writerows(results)utf-8-sig带 BOM 头,Excel 直接双击打开不乱码,这是交付给运营或做报表的同事时最省事的编码方案。
5. 进阶排错:shp 转 gdb、ShapeChecker 修复、只保留外边界线
5.1 shp 转 gdb 与边界坐标导出成 txt
企业交付场景常要求把 shp 转成 File Geodatabase,用 ogr2ogr 一条命令完成:
ogr2ogr -f "FileGDB" 昆明数据.gdb 昆明各乡镇街道.shp -nln 乡镇街道-f "FileGDB"指定输出格式,-nln 乡镇街道指定图层在 gdb 里的名称。注意社区版 GDAL 默认不带 FileGDB 写入驱动,如果报驱动不支持,改用-f "OpenFileGDB"输出,写操作需安装 Esri 官方驱动才能用。
做三维可视化或 Web 端渲染时,常需要把边界坐标导出成文本,shp 转 txt 的常见做法是逐要素输出顶点坐标:
import shapefile sf = shapefile.Reader("昆明各乡镇街道.shp") with open("昆明边界.txt", "w", encoding="utf-8") as out: for shp in sf.shapes(): parts = [f"{seg[0]},{seg[1]}" for seg in shp.points] out.write(";".join(parts) + "\n")每行是一个乡镇街道的全部顶点,点对用逗号分隔,要素间用分号分隔。导出后若还要对接 3dtiles 管线,一般先经过 GeoJSON 过渡格式,再走转换工具,这条 txt 只是中间检查用的。注意区分原始坐标系是经纬度还是投影米制,交付说明里写清楚,否则前端拿六位数的投影坐标直接画图必然错位。
5.2 用 ShapeChecker 修复 shp 拓扑错误
shp 经过多次编辑合并后,容易产生自相交、重复节点、空几何这类问题,直接影响第 3 章邻接判断的结果。ShapeChecker 修复的常见步骤是:打开工具加载目标 .shp,检查项勾选自相交、重复节点、无效环,执行扫描后在结果列表里定位错误要素的编号和类型,设置搜索容差后统一修复,最后导出到新文件,不要覆盖原文件。
修复完成后再跑一次邻接判断或点面包含,之前因缝隙导致的漏判一般能解决。如果修复后仍错位明显,问题不在拓扑而在数据精度——两个不同来源的图层边界本身不重合,这不属于文件损坏,需要用边缘捕捉工具对齐,而不是反复修拓扑。做渔网分割 shp 这类网格拆分时,也建议先跑一遍 ShapeChecker,几何不合法的网格化结果会直接影响后续面积统计。
5.3 只保留外边界线:合并与分组聚合
行政区划图只要昆明市外轮廓、不要内部街道线时,用 QGIS 的「矢量 > 地理处理 > 合并」工具,把所有街道要素合并成一个要素,得到的就是去除内部边界的市级外轮廓。要保留区县外边界而去掉乡镇边界,就在合并工具里按名称字段分组,输出是各区县的多面要素,内部街道边界自动消除。
外边界提取出来后有轻微锯齿是正常现象,想更平滑可以用「平滑」工具做低强度处理。但要记住平滑是破坏性操作,边界会向内部收缩,面积略小于真实值,论文数据尽量保持原样。
提示:合并、平滑都是破坏性操作,操作前先复制一份原始 shp 文件族,后续想恢复乡镇边界时直接重新解压,不要依赖撤销。
最后交付时,把修复后的图层、坐标系说明和字段对照表放同一个文件夹,压缩包命名带上日期和坐标系,比如昆明乡镇街道_2025_CGCS2000.zip,半年后自己或同事续用都能直接上手。
本文还有配套的精品资源,点击获取