甘肃shp数据完整实操指南:坐标校验、投影转换与格式互转
简介资源为甘肃省基础地理要素的矢量数据包Shapefile格式面向GIS开发者、规划师与地理信息课程学习者适用于地图底图制作、空间叠置分析、设施分布、生态环境评价等场景。压缩包共225个文件其中39组shp/dbf/shx/prj为核心数据文件shp保存几何坐标、dbf保存属性表、shx提供索引、prj定义投影坐标系辅以sbx/sbn空间索引与mxd地图工程文件便于在ArcGIS及QGIS中直接打开。压缩包大小仅17.3MB轻量易用当前已有3028人浏览学习。数据内容精细覆盖省市县行政边界、国道省道县乡道及高速公路、单线水系、乡镇居民地、加油站与旅游景点等要素可支撑地理信息课程案例、区域路网规划、旅游资源评估及简单GIS分析项目是一份兼顾完整性与可操作性的基础地理信息数据集。1. 拿到甘肃基础数据shp包第一件事不是打开ArcGIS而是先验坐标一份标注“【最新版】甘肃基础数据完整版矢量shp格式.rar”的数据包解压之后很多人习惯性双击加载到 ArcGIS 里看图形好不好看。我的建议是反过来把这包数据当成一个黑匣子先回答三个问题——坐标系是什么、属性表是什么编码、面要素有没有拓扑破损。这三个问题不解决后面做的县域边界提取、dwg叠加、转3dtiles、算面积全都会在某个环节翻车而且越往后查越难定位。这份数据能帮你省掉重新矢量化甘肃全省边界的重复劳动适合做区域分析、WebGIS 可视化、CAD 底图叠加和县域行政区划边界提取的从业者。值不值得用取决于你投在数据检查上的第一个小时而不是数据包描述的版本号。2. 检查与投影用GDAL/GeoPandas把甘肃shp的坐标系底子盘清楚2.1 三条命令行看清shp里面到底是什么拿到shp先不要急着拖进软件用 GDAL 的命令行工具ogrinfo做一次快速体检。它在 Windows 和 Linux 下都能用装了 QGIS 或 OSGeo4W 就自带。ogrinfo -so 甘肃省.shp ogrinfo -al -so 甘肃省.shp ogrinfo -geomSUMMARY 甘肃省.shp第一条输出这个 shp 的图层名和要素类型第二条不带-so的概要模式会列出字段列表和要素数量第三条带-geomSUMMARY会额外输出几何类型和空间范围。-so是-summary的简写只输出汇总信息不逐条打印要素文件再大也不会刷屏。我一般还会用 Python 的 GeoPandas 把属性结构完整读出来因为光看 ogrinfo 的字段列表看不到字段里实际存的是什么值。import geopandas as gpd gdf gpd.read_file(甘肃省.shp, encodingutf-8) print(gdf.crs) # 看坐标系定义 print(gdf.dtypes) # 看字段类型 print(gdf.head(3)) # 看前几行属性值确认字段名是否可读encodingutf-8是重点参数。如果属性里是中文而 shp 实际是 GBK 编码这里会读出一堆乱码或直接报编码错误。遇到这种情况把参数改成encodinggbk再读。判断标准很简单打印出来的列名和属性值是正常中文编码就对了是锟斤拷或者????这样的乱码就换另一个编码试。2.2 CGCS2000三度带与WGS84甘肃数据该用哪个坐标系甘肃东西跨度大从东经 92° 到 110° 左右。省级基础数据最常见的两种坐标系是 WGS84 地理坐标系EPSG:4326和 CGCS2000 高斯-克吕格投影坐标系。如果数据包来源是自然资源系统大概率是 CGCS2000 分带投影如果来源是互联网地图或 GPS 采集数据多半是 EPSG:4326。这两种坐标直接叠加甘肃中西部会错位几十到几百米肉眼可能看不出但落在乡镇一级就完全对不上。坐标系EPSG类型适用场景WGS 844326经纬度地理坐标在线地图、GPS采集、跨省大范围预览CGCS2000 / 3-degree Gauss-Kruger CM 102E4547投影坐标米兰州周边、河西走廊东段距离与面积量算CGCS2000 / 3-degree Gauss-Kruger CM 105E4548投影坐标米张掖以东至庆阳部分区域CGCS2000 / 3-degree Gauss-Kruger zone 344546投影坐标米省级大范围制图分带统一管理判断数据当前坐标系最直接的办法是看同目录下的.prj文件。用文本编辑器打开它里面写着GCS_WGS_1984就是经纬度写着CGCS2000_3_Degree_GK_CM_102E就是 102 度中央经线的投影坐标。注意一个坑.prj文件里的描述和实际坐标值可能不一致旧数据常见这种情况所以后面要结合已知地物坐标做校验。2.3 统一投影后再存盘一个必须写.cpg的细节处理甘肃省级数据我通常先确认源坐标系再统一转到一个目标坐标系。做面积和距离统计时用投影坐标做跨省拼接时保留经纬度。gdf_wgs gdf.to_crs(EPSG:4326) # 转经纬度用于范围预览 gdf_proj gdf.to_crs(EPSG:4547) # 转102度带投影用于量算 gdf_proj.to_file(甘肃省_4547.shp, encodingutf-8)to_crs是重投影不是简单改写坐标值。转完之后原来面的顶点坐标会重新计算位置对应的还是同一个地方但单位从度变成了米。to_file写出时encodingutf-8会让属性字段以 UTF-8 写入同时 GDAL 会自动生成一个.cpg文件记录编码。提示往 ArcGIS 环境交付数据时最好确认 shp 同目录下有.cpg文件。没有这个文件ArcGIS 默认按本地语言编码读中文属性经常变成乱码。这是 shp 数据交接时最常见的血泪经验之一。3. 按县域与地市拆数据从省级矢量里提取行政区划边界的实操3.1 用行政区划码字段过滤出甘肃县域省级基础数据通常是全省一张面图层里面包含所有市、县、乡镇的边界。做项目时经常只要某个市或某几个县的数据这时候按行政区划码过滤是最稳的做法。甘肃省的行政区划码以“62”开头比如兰州市是 6201 开头下属区县是 620102 这样的六位码。import geopandas as gpd gdf gpd.read_file(甘肃省.shp, encodingutf-8) print(gdf.columns.tolist()) # 先看字段名确认行政区划码字段叫什么 # 假设字段名是 XZQHDM取甘肃全省县域数据 counties gdf[gdf[XZQHDM].str.startswith(62)] # 如果要提取某个地市比如兰州市取前四位等于6201 lanzhou gdf[gdf[XZQHDM].str.startswith(6201)] lanzhou.to_file(兰州市县域.shp, encodingutf-8)startswith(62)是按字符串前缀过滤不是数字比较。省级 shp 里的行政区划码字段经常是字符串类型直接 62会匹配不到任何数据。字段名不固定不同来源的数据可能叫XZQHDM、PAC、QHDM所以先执行print(gdf.columns.tolist())确认。如果字段名是数字类型先转成字符串再过滤counties gdf[gdf[XZQHDM].astype(str).str.startswith(62)]3.2 属性清洗去重、查空值、修正无效几何从网上下载的数据包属性表里难免有重复记录、空值和坏几何。直接拿去做后续分析统计结果会对不上切成 3dtiles 时还可能让切片工具崩溃。# 去重按行政区划码保留第一条 gdf_clean gdf.drop_duplicates(subsetXZQHDM) # 检查空值 print(gdf_clean[gdf_clean[XZQHDM].isna()]) # 过滤掉无效几何 gdf_clean gdf_clean[gdf_clean.geometry.is_valid] # 按地市名聚合合并县界成市界 city gdf_clean.dissolve(by城市名称, as_indexFalse) city.to_file(甘肃省地市边界.shp, encodingutf-8)drop_duplicates的subset参数指定按哪个字段去重如果不传会要求整行都一样才算重复。dissolve是按属性合并几何把县级面拼成地市级面by参数传的是分组字段名。注意 dissolve 之后原始属性只剩分组字段其他字段会被丢弃所以要在清洗阶段把要保留的字段处理完。3.3 拓扑检查与修复别把带缝隙的面发给下游省界、县界矢量化过程中经常出现相邻面不共边、有重叠或中间夹缝隙的情况。做可视化看不出来但做空间分析时面积会算多、算少叠加分析也会有偏差。我用 shapely 的检查函数快速定位问题面from shapely.validation import explain_validity invalid gdf_clean[~gdf_clean.geometry.is_valid] for idx in invalid.index: reason explain_validity(invalid.loc[idx, geometry]) print(f要素 {idx} 无效: {reason})输出结果里常见的提示是Self-intersection自相交和Ring Self-intersection环自相交。这些都是面边界自身打结造成的修复常用buffer(0)技巧gdf_fixed gdf_clean.copy() gdf_fixed[geometry] gdf_fixed.geometry.buffer(0)buffer(0)是 Shapely 里的经典修复杂技作用不是真的创建缓冲区而是让几何对象重新组织边界消除自相交。对于轻微拓扑问题这一步能直接救回来如果报错TopologyException说明几何损坏严重得回到原始数据源重新矢量化。4. 格式互转的三条实用路线dwg转shp、shp转3dtiles、shp转txt4.1 dwg转shpCAD底图怎么叠到甘肃矢量上做自然资源或测绘项目时经常拿到设计院的 dwg 图纸需要叠到甘肃行政边界上核对。dwg 是 CAD 原生格式GIS 软件不能直接读常见的做法是在 CAD 里把图纸另存为 dxf再用 ogr2ogr 转成 shp。GDAL 的高版本对 dxf 支持很成熟对 dwg 则需要单独编译插件通用环境里容易踩坑。ogr2ogr -f ESRI Shapefile 陇南_道路.shp 陇南_道路.dxf \ -nlt PROMOTE_TO_MULTI \ -lco ENCODINGUTF-8-f指定输出格式-nlt PROMOTE_TO_MULTI把原来可能破碎的多段线统一转成 MultiLineString避免一个要素拆成多行。-lco ENCODINGUTF-8让输出的 dbf 属性表用 UTF-8 编码不然中文图层名或字段值会乱码。转完之后必须做三件事第一确认坐标偏移。CAD 图纸常用地方坐标系或毫米单位转出来的要素经常偏移到不知道哪里去了。先查看范围再根据已知控制点做平移或重投影。第二确认线面关系。CAD 里的闭合多段线转过来默认是线不是面要后续手动构建面。第三清理冗余图层。dwg 里大量辅助线、标注图框都会一起转出来可以在 CAD 里提前关掉或删除。4.2 shp转3dtiles把甘肃省界搬进Web三维场景shp 转 3dtiles 是 WebGIS 可视化里的高频需求把行政边界接到 Cesium 场景里做三维展示或查询。3dtiles 是面向海量数据的瓦片格式shp 直接转会有两个问题数据量太大导致切片慢、边界线过于复杂导致加载卡顿。常见做法是先在 GIS 软件里做一步简化再交给切片工具处理。简化用简化几何工具容差参数是关键。在经纬度坐标下容差设 0.001 度左右基本看不出变化但顶点数量能降一半设到 0.01 度边界细节会明显变粗糙。做省级边界展示我一般用 0.005 度先试切看效果再调整。切完的 b3dm 瓦片加载到 Cesium 里后还有一个常见显示问题边界是平的没有贴在地形上。处理方式是在切片工具里设置贴地模式让它沿地形高度做 GPU 贴合如果地形数据缺失就在加载时强制指定高度偏移。这里没有统一参数不同工具的叫法不一样但逻辑都是“按地形贴合”或“固定高度”二选一。4.3 shp转txt导出坐标点给外业设备和老系统shp 转 txt 的场景多数是要把面状要素的中心点坐标或边界点坐标导出来给老系统导入或外业设备使用。这类需求用 GeoPandas 最方便控制字段和格式都灵活import geopandas as gpd gdf gpd.read_file(甘肃省_4547.shp, encodingutf-8) gdf_wgs gdf.to_crs(EPSG:4326) # 取面要素质心经纬度 gdf_wgs[lng] gdf_wgs.geometry.centroid.x gdf_wgs[lat] gdf_wgs.geometry.centroid.y # 只保留需要的字段导出制表符分隔 out gdf_wgs[[城市名称, lng, lat]] out.to_csv(甘肃地市坐标.txt, sep\t, indexFalse, encodinggbk)注意centroid求的是质心不是重心对不规则面状要素可能有偏差。如果要把边界点坐标全部导出需要用get_coordinates()展开所有顶点。编码方面老系统很多只认 GBK所以这里encodinggbk比 utf-8 更稳妥。反过来如果 txt 要交给 Linux 下的程序处理就保持 utf-8。坐标顺序xlng, ylat是固定约定导出的文本里如果要按“纬度,经度”排记得交换列顺序。5. 甘肃shp数据避坑指南坐标偏移、乱码、面破损与面积算错5.1 叠加后错位几百米坐标系没对准现象把甘肃行政边界和遥感影像或 GPS 轨迹叠加时边界整体向西或向东偏移几百米局部地区偏移量还不一样。原因shp 的.prj文件描述的是 CGCS2000但坐标值实际是 WGS84 采集的或者反之。这类数据通常经过别人二次另存投影定义被软件自动写错了。另一个常见原因是三度带选错兰州市区用 102 度中央经线的数据去和 105 度带的数据叠加必然错位。解决用已知坐标的地物做校验。找两三个经纬度明确的点状地标比如政府驻地或桥梁在数据里读出对应坐标反推实际坐标系。确认后统一用to_crs重投影到同一个 EPSG不要手动加减坐标值那样会破坏几何拓扑。5.2 属性表中文变乱码编码与.cpg的纠葛现象打开 shp 属性表中文全变成乱码或者第一次打开正常换个软件打开就乱。原因ESRI Shapefile 的 dbf 属性表没有强制编码标准。数据生产方用 UTF-8 写入但没生成.cpg文件时ArcGIS 会按本地语言 GBK 去读自然显示乱码。反过来GBK 编码的数据被 QGIS 默认按 UTF-8 读同样是乱码。解决QGIS 加载时手动指定数据源编码在“数据源管理器”里选择 UTF-8 或 GBK 试。确认哪种编码能正确显示后用 GeoPandas 重新读取再以它为准导出并生成.cpggdf gpd.read_file(甘肃省.shp, encodinggbk) gdf.to_file(甘肃省_编码修复.shp, encodingutf-8)写入完成后检查输出目录确认出现了.cpg文件再发给任何下游都稳了。5.3 合并求面积全错了几何自相交与投影单位现象用 dissolve 合并地市边界后用area算面积兰州市的面积算出来只有 0.00013明显不对。原因几何对象还是经纬度坐标系area返回的单位是度²不是平方公里。另一种情况是 dissolve 之后相邻面之间有重叠或缝隙area会把重叠部分重复计算。解决先转投影坐标系再用 GIS 的面积公式算。GeoPandas 里要先to_crs(EPSG:4547)再算area结果单位是平方米除以一百万就是平方公里。算完后用前面提过的buffer(0)修复几何再重算一遍对比两次数值差超过 1% 就说明拓扑有问题。5.4 转换后字段丢失或名称变了shp格式的硬性限制现象dwg 转 shp 后CAD 里的长中文属性名变成了一串短字符shp 转 3dtiles 后属性表只剩几个默认字段。原因ESRI Shapefile 的字段名最长支持 10 个字符超出会被截断。中文一个字符算一个超过 5 个中文字符就会被裁剪。3dtiles 的 b3dm 默认只带少量属性需要手动勾选要保留的字段。解决转换前在源软件里把字段名改短或用英文字段名。转 3dtiles 时在切片工具的属性设置里显式勾选展示字段不要相信默认带全部属性的选项。6. 渔网分割与GIS二次开发把甘肃数据接进自己的工具链6.1 用渔网工具把全甘肃切成可并行处理的块甘肃全省面积大要素多一次性做空间分析或切片经常内存爆炸。常见的做法是用渔网分割把省界切成一格一格的规则图块每个图块单独处理最后再合并结果。QGIS 里路径是“矢量 → 研究工具 → 创建渔网”范围选甘肃省 shp 的外包矩形网格间距按投影坐标设 10 公里甘肃东西约 1600 公里会生成一万多个网格。生产环境这么玩有点重更实用的场景是按市或流域去切网格间距设 100 公里只切出覆盖目标区域的格子import geopandas as gpd from shapely.geometry import box gdf gpd.read_file(甘肃省.shp, encodingutf-8) minx, miny, maxx, maxy gdf.total_bounds # 按0.5度间距生成渔网 cells [] x minx while x maxx: y miny while y maxy: cells.append(box(x, y, x 0.5, y 0.5)) y 0.5 x 0.5 grid gpd.GeoDataFrame(geometrycells, crsgdf.crs) intersected gpd.overlay(gdf, grid, howintersection) intersected.to_file(甘肃_渔网分割.shp, encodingutf-8)total_bounds取的是全要素范围box生成单个格网矩形overlay做空间相交。0.5 度在甘肃中部的实际距离约 50 公里左右适合中等粒度分析。参数按需调整越小切得越碎计算越慢。6.2 用GeoPandas把shp变成后端接口数据GIS 二次开发里最常见的诉求是把 shp 数据接到自己的 Web 或桌面系统里而不是依赖桌面 GIS。后端读取 shp 最省事的方式是 GeoPandas 读出后转 GeoJSON再通过接口返回给前端。from flask import Flask, Response import geopandas as gpd app Flask(__name__) app.route(/api/gansu) def gansu(): gdf gpd.read_file(甘肃省_4547.shp, encodingutf-8) gdf_simplified gdf.simplify(0.01, preserve_topologyTrue) return Response( gdf_simplified.to_json(), mimetypeapplication/json ) if __name__ __main__: app.run(host0.0.0.0, port5000)simplify(0.01)是简化容差在投影坐标下表示 0.01 米在经纬度下表示 0.01 度。给前端展示时用简化后的数据能大幅减小接口体积。前端加载 GeoJSON 后直接渲染到 Leaflet 或 OpenLayers就完成了 shp 数据的二次开发接入。需要写权限的话反向操作就是把前端回传的 GeoJSON 读回 GeoPandas再to_file写成 shp。这个方案里最值得记住的教训是shp 数据进系统之前坐标系、编码、拓扑三件事必须提前处理完不要指望前端或数据库帮你纠错。我自己就曾把一个投影信息写错的甘肃边界直接丢进空间数据库结果所有空间查询都偏了差不多 800 米排查了整整一个下午。从那以后任何来源的 shp 数据我第一件事永远是看.prj、看编码、跑一遍拓扑检查。数据格式本身不难难的是让每个环节的人都遵守这组习惯。希望帮到你。本文还有配套的精品资源点击获取