ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

烟台行政区划SHP数据处理:修复、转换与发布指南

烟台行政区划SHP数据处理:修复、转换与发布指南 简介烟台各区县行政区划shp文件是一份面向GIS开发者、城乡规划从业者及地理信息科研人员的矢量地理数据资源解决在烟台市范围内进行地图制图、空间分析或可视化时缺乏标准行政边界的问题。压缩包内共14个文件包含.shp几何数据、.shx空间索引、.dbf属性表、.prj投影坐标系以及.sbn/.sbx空间索引和.xml元数据等Shapefile必需组成可被ArcGIS、QGIS等主流GIS平台直接读取并用于边界叠加、面积量算和专题制图整体仅141KB轻量易用。该资源目前已有425人学习/下载实用性得到一定验证。数据按烟台各区县精细划分附带属性信息与坐标参考适合城市研究、商业选址、政务可视化等场景可省去自行抓取、清洗边界数据的烦琐过程切入项目后即可快速投入应用。尤其适合需要快速搭建烟台市底图的读者解压后即可在GIS软件中直接调用。1. 拿到烟台行政区划 SHP先别急着用做 GIS 相关开发或数据分析的人迟早会碰上行政区划数据。网上流传的“烟台各区县shp文件.rar”这类压缩包通常是某个时间点从公开地图源或统计部门基础地理数据里裁切出来的包含芝罘区、莱山区、福山区、牟平区、开发区、蓬莱区、龙口市、莱阳市、莱州市、招远市、栖霞市、海阳市这些区县的行政边界。下载解压之后里面一般是.shp、.shx、.dbf、.prj这几个配套文件polygon 类型坐标系多为 CGCS2000 或 WGS84。这个标题的核心其实不是“下载”而是“拿到手之后怎么正确处理”。很多人打开发现属性表字段对不上、边界和现状不一致、投影坐标系缺失、要素里有碎屑或重叠就直接卡住。实际上做区县级行政区划数据处理有一套固定的流程先检查坐标系和地理范围再修复合集的几何错误接着转换投影坐标系最后根据业务需要导出成需要的格式。这套流程处理烟台数据时有它特有的坑比如跨海岛屿的归属、新旧区划调整的边界差异以及栅格数据配准时坐标系不统一的问题。下面按常见做法展开从检查到修复、从转换到导出把能用命令和代码解决的问题都写清楚。适合刚接触行政区划数据分析的初级工程师也适合需要把烟台数据接入自有系统的后端或数据处理工程师参考。2. 解开 RAR 后先做三件事检查 SHP 完整性、坐标系和要素属性RAR 压缩包解压出来后第一步不是直接拖进 ArcMap 或 QGIS而是先做基础体检。SHP 格式需要至少三个配套文件才能用.shp存几何、.shx存索引、.dbf存属性缺任何一个都会导致加载失败。.prj文件用来记录坐标系如果解压后没有.prj软件会默认按未知坐标系处理后面所有投影转换和面积计算都不可信。2.1 用 Python 检查 SHP 文件完整性的最小代码不管做不做开发检查文件完整性这一步用 Python 最省事。以下代码可以在没有 ArcGIS 环境的机器上运行只依赖pyshp这个轻量库。import shapefile # 以烟台各区县 shp 文件为例 sf shapefile.Reader(yantai_counties.shp) # 1. 检查几何数量与记录数量是否一致 print(shapes 数量:, len(sf.shapes())) print(records 数量:, len(sf.records())) # 2. 检查每个要素的几何类型是否为面 shape_type sf.shapeTypeName print(几何类型:, shape_type) # 3. 检查字段名和字段类型 fields sf.fields for field in fields[1:]: # 第一个是 DeletionFlag跳过 print(字段名:, field[0], | 字段类型:, field[1], | 宽度:, field[2]) # 4. 检查最小外接矩形bounding box bbox sf.bbox print(数据范围: minx%f, miny%f, maxx%f, maxy%f % (bbox[0], bbox[1], bbox[2], bbox[3]))这段代码干的事情很直接。shapefile.Reader读取整个文件len(sf.shapes())和len(sf.records())必须相等如果不相等说明文件损坏或写入时中断。几何类型必须显示为POLYGON如果出现POINT或POLYLINE说明数据根本不是行政区划面。字段信息会列出类似NAME、code、area这样的字段方便确认是否包含区县名称字段。bbox输出的范围可以用来验证数据确实是烟台——烟台的经度范围大致在东经 119.3° 到 122.7° 之间纬度在北纬 36.2° 到 38.4° 之间如果范围完全对不上说明包里的数据张冠李戴。2.2 坐标系缺失时用 GDAL 直接读写.prj文件检查完基本完整性后接下来要看坐标系。用文本编辑器打开.prj文件如果里面是一串带GEOGCS或PROJCS的文本说明坐标系信息是完整的。如果文件不存在或内容为空需要人工补写。烟台各区县的 shp 文件如果是早年公开数据坐标系大概率是CGCS2000 / 3-degree Gauss-Kruger zone 38对应 EPSG 代码 4547另一种常见情况是西安 1980 或北京 1954 投影坐标系。补写.prj文件不需要打开 GIS 软件用 GDAL 一行命令就能完成ogr2ogr -a_srs EPSG:4547 yantai_counties_cgcs2000.shp yantai_counties.shp这条命令的原理是把原始文件复制一份同时在输出文件上强制写入坐标系信息。-a_srs的意思是 assign SRS不加它会保留原始文件的坐标系定义加了它会覆盖或补充坐标系定义。EPSG:4547是 CGCS2000 / 3-degree Gauss-Kruger zone 38 的 EPSG 代码覆盖包括烟台在内的山东半岛东部区域。做完这步后再用ogrinfo命令验证ogrinfo yantai_counties_cgcs2000.shp -so -al | grep -E EXTENSION|Geometry|Layer SRS输出结果中Layer SRS WKT和EXTENSION部分会显示新的坐标系定义。这里需要注意ogr2ogr默认会重建所有几何和属性如果原文件本身就带有损坏的几何转换过程有可能报错因此建议先执行完 3.1 节的修复步骤再补坐标系。3. 修复合集中的几何错误与拓扑问题防止面积统计或出图裁切时翻车烟台各区县的行政区划 shp 虽然看起来是一个完整的面图层但用空间分析和制图场景往下挖几何问题非常多。常见的有三类面与面之间有微小缝隙、边界线自相交、存在面积很小且高度细碎的碎片多边形。这些问题在普通显示时不明显但一旦做面积计算、缓冲区分析、拓扑叠置结果错误就会被放大到可以查觉的程度。3.1 用 GDAL 的 ogr2ogr 修复基本几何错误GDAL 的ogr2ogr内置了-makevalid参数能自动修复大部分自相交和非简单几何错误。以下命令对烟台数据执行修复并输出新文件ogr2ogr -makevalid -f ESRI Shapefile yantai_counties_valid.shp yantai_counties.shp-makevalid的逻辑是调用 GEOS 库对每个要素的几何进行标准化把自相交的面拆分成多个简单多边形把空几何删除然后把有效的部分合并回去。这一步解决的是“单个要素内部不能有效表达”的问题但要注意它不会自动消除相邻面之间的缝隙。烟台市的行政区划数据里芝罘区作为中心城区历史上曾与周边区县边界存在部分弹性界线某些版本的 shp 数据在区县交界地带会有几米到几十米的空隙这类问题更适合用拓扑修复工具。3.2 使用 ShapeChecker 或 QGIS 拓扑检查器定位边界缝隙shapechecker修复shp步骤这个热词能出现在检索里说明很多人确实遇到过边界缝隙或重叠的问题。形状检查工具有不少开源层面 QGIS 自带拓扑检查器商业层面有专业的几何修复插件但要在命令行下做批量修复最实用的路径是 QGIS 处理算法中的Fix geometries。下面是 QGIS Python 控制台里运行修复脚本的写法import processing from qgis.core import QgsVectorLayer, QgsProject # 加载原始图层 layer QgsVectorLayer(yantai_counties_valid.shp, yantai_original, ogr) if not layer.isValid(): print(图层加载失败) # 运行修复几何算法 result processing.run(native:fixgeometries, { INPUT: layer, OUTPUT: memory:fixed_layer }) fixed_layer result[OUTPUT] QgsProject.instance().addMapLayer(fixed_layer) print(修复完成要素数:, fixed_layer.featureCount())native:fixgeometries和前面ogr2ogr -makevalid本质相同不过提供了更精细的选项。如果执行后要素数量发生变化比如从 12 个增加到 15 个说明原始数据存在多部分多边形被拆分的情况这也是排查问题的一个抓手。边界缝隙的检查需要另外使用 QGIS 的拓扑规则工具新建拓扑规则“不能有缝隙”容差设置为 0.001 度约等于 100 米左右的判断阈值由系统列出所有缝隙多边形再人工决定是合并到相邻区县还是保持现状。这里常见误用是直接不加容差检查导致微小缝隙也报错实际处理时应该根据数据用途决定容差制图用 0 容差统计用 100 米以下容差都可接受。3.3 渔网分割和只保留外边界这两个经典需求的做法热词里出现“渔网分割shp”和“shp有没有办法只保留外边界线”说明实际操作中还有两个高频处理需求。渔网分割常用于把行政区划面切分成规则网格然后做人口分布或路网密度统计。执行方法是 QGIS 的Create grid创建渔网再用Clip功能把烟台面图层作为裁剪范围。命令行下则可以直接用 GDAL# 创建一个覆盖烟台范围、边长为 1km 的渔网 ogr2ogr -f ESRI Shapefile grid_1km.shp -dialect sqlite -sql SELECT * FROM (SELECT ST_SquareGrid(0.01, geometry) AS geometry FROM yantai_counties_valid) yantai_counties_valid.shpST_SquareGrid是 SpatiaLite 扩展提供的函数0.01是网格边长单位取决于输入数据的坐标系。如果数据是地理坐标系0.01 度约合 1.1 公里如果数据是投影坐标系则需要改用米为单位。只保留外边界线的需求对应热词shp有没有办法只保留外边界线做法是先把所有区县面要素合并成一个整体再提取边界线。这个操作在 QGIS 里叫Dissolve然后Polygons to lines命令行下用 GDAL 的 SQL 也能完成ogr2ogr -f ESRI Shapefile yantai_boundary_line.shp yantai_counties_valid.shp \ -dialect sqlite -sql SELECT ST_Boundary(ST_Union(geometry)) AS geometry FROM yantai_counties_valid这条命令的输出是一个线要素图层包含烟台市的外边界和所有内部区县界线。如果想要只保留外部轮廓需要在外边界线的提取逻辑中排除公共边这个用 GDAL 做会比较复杂直接转到 QGIS 的Dissolve后使用Polygonize形成的面转线再手动删除内在边界线。实际工作中如果只需要总边界直接使用ST_ExteriorRing配合ST_Union效率更高。4. 将经纬度 Excel 数据导入并生成 SHP以及坐标系转换的几个关键参数热词中“怎么把excel中经纬度数据导入arcmap中生成shp文件”排得很高说明很多人的需求链路是“烟台各区县 shp 的边界数据已经有了但我要把自己手里的点数据叠加上去”。这个场景下正确处理顺序是先导入点数据生成点图层再与行政区划面图层做空间连接最后统一坐标系后输出或做可视化。4.1 Excel 经纬度导入 QGIS 后用 SQL 生成点要素假设 Excel 有两个字段lng和lat存的是 WGS84 经纬度。在 QGIS 中使用“导入带坐标的 CSV”即可但如果要批量处理或避免界面操作可以用 Python 结合 OGR 直接生成 shp。以下是最小代码import csv import ogr import osr # 创建点图层坐标系设为 WGS84 driver ogr.GetDriverByName(ESRI Shapefile) data_source driver.CreateDataSource(points_from_excel.shp) srs osr.SpatialReference() srs.ImportFromEPSG(4326) layer data_source.CreateLayer(points, srs, ogr.wkbPoint) # 添加字段 field_name ogr.FieldDefn(name, ogr.OFTString) field_name.SetWidth(50) layer.CreateField(field_name) # 读取 Excel 导出的 csv 文件 with open(coords.csv, r) as f: reader csv.DictReader(f) for row in reader: point ogr.Geometry(ogr.wkbPoint) point.AddPoint(float(row[lng]), float(row[lat])) feature ogr.Feature(layer.GetLayerDefn()) feature.SetGeometry(point) feature.SetField(name, row.get(name, )) layer.CreateFeature(feature) data_source None print(点文件生成完成)代码中srs.ImportFromEPSG(4326)表示坐标系定义为 WGS84生成的.prj文件会自动带上相应的坐标系定义之后和烟台区县 shp 一起加载时QGIS 或 ArcGIS 会自动判断坐标系是否匹配。如果烟台 shp 是 CGCS2000 投影坐标系会出现坐标系不统一的情况需要用下面 4.2 节提到的方法转换。这一步的常见误用是在 Excel 里直接把经纬度写进 ArcMap 的 Add XY Data 功能然后保存为事件图层再导出为 shp两步走确实没有问题但如果 Excel 中经纬度的字段名带了中文字符或有空格ArcMap 的自动识别会失效所以用 Python 生成的方式可控性更强。4.2 投影转换烟台数据用 CGCS2000 还是 WGS84 取决于用途“eps地图转为shp”和“shp转gdb和gdb是一样的东西吗”这两个热词背后核心仍然是坐标系的选择。烟台区县数据在用于面积统计和距离计算时首选投影坐标系CGCS2000 / 3-degree Gauss-Kruger zone 38EPSG:4547覆盖烟台完全够用中央经线为 120°E烟台大部分区域在 119.3°E 到 122.7°E 之间跨了两个 3 度带所以实际使用时可能需要 zone 37中央经线 111°E和 zone 38中央经线 120°E两套数据接边。如果要把数据发布到 Web 地图上通常转换为 EPSG:3857Web Mercator如果要做经纬度坐标提取直接用 EPSG:4326。下面是用 GDAL 执行转换的命令# WGS84 经纬度转 CGCS2000 高斯投影 ogr2ogr -t_srs EPSG:4547 yantai_counties_4547.shp yantai_counties_wgs84.shp # 再转 3857 用于 web 可视化 ogr2ogr -t_srs EPSG:3857 yantai_counties_3857.shp yantai_counties_4547.shp这里要理解-t_srs和前面-a_srs的区别。-t_srs是真正的坐标系转换会根据两个坐标系之间的地理变换参数重新计算每个顶点的坐标-a_srs只是给文件加一个坐标系标签不改变坐标值。如果把-t_srs用在没有.prj的文件上GDAL 会先按未知坐标系处理输出的坐标值会出现极大偏差所以顺序必须严格为“先补坐标系再转换”。如果你手里的 shp 是 ArcGIS 的 File Geodatabase 格式gdb可以用ogr2ogr直接转换成 shpogr2ogr -f ESRI Shapefile yantai_from_gdb.shp /path/to/data.gdb yantai_counties关于热词“shp转gdb和gdb是一样的东西吗”结论很明确gdb 是 Esri 的数据库容器支持拓扑、网络数据集、版本管理shp 是开放格式不能存储拓扑关系。批量转换时 gdb 转 shp 用ogr2ogr逐个要素类处理shp 转 gdb 也是同样命令目标格式改为FileGDB即可。4.3 热词“shp转txt”和“shp转3dtiles”在实际项目里的处理方式热词里有“shp转txt”和“shp转3dtiles”。shp 转 txt 的本质是提取几何坐标和属性到文本文件常用于给 Web 前端直接渲染或给算法训练做输入。以下 Python 代码可以读取 shp 并输出一份按区县聚合的边界坐标文本import shapefile import json sf shapefile.Reader(yantai_counties_4547.shp) # 输出为 GeoJSON 结构再按需转 txt data { type: FeatureCollection, features: [] } for shape, record in zip(sf.shapes(), sf.records()): geojson shape.__geo_interface__ props dict(zip([f[0] for f in sf.fields[1:]], record)) data[features].append({ type: Feature, properties: props, geometry: geojson }) with open(yantai_counties.txt, w, encodingutf-8) as f: f.write(json.dumps(data, ensure_asciiFalse, indent2)) print(转换完成要素数量:, len(data[features]))生成的是标准 GeoJSON 的 txt 文本用于 Leaflet、Mapbox GL、ECharts 的 geo 组件都直接支持不需要额外解析。shp 转 3dtiles 主要用于三维地球可视化和倾斜摄影模型的叠加。常用工具链是先把 shp 转为 GeoJSON再用CesiumGS/3d-tiles-tools或py3dtiles转换但由于区县平面边界是二维 polygon3dtiles 里以 extruded polygon 的方式表现即给每个区县设置一个高度比如 50 米形成立体的行政区块。如果你的目标是做可视化而不是白模建议直接使用 QGIS 的Qgis2threejs插件导出 glTF再由工具转成 3dtiles。整个链路里最常见的错误是坐标参考系不统一三维场景通常用 EPSG:4978地心坐标系或 EPSG:4326 经纬度高度直接用 4547 的数据会导致模型偏离真实位置。5. 批量压缩单个或多个 SHP 时RAR 的算法选择和压缩率实测依据标题里的rar是另一个容易被忽略但实际影响很大的技术点。一个 shp 文件通常不大区县级行政区划一般几十 KB 到几 MB但一堆区县放在一起、又附带多个版本时文件夹体积就会膨胀。行政区划的 shp 主要由坐标点构成边界坐标有大量重复位数压缩率很高。5.1 单个或多个 SHP 批量压缩的推荐命令热词“单个shp如何批量压缩”说明不少人卡在“如何把 12 个区县 shp 文件全部压进同一个 rar 包”上。这里给出 WinRAR 和 Linux 环境下的两种方案。Windows 图形界面下如果需要批量处理多个目录建议先按区县建子文件夹每个子文件夹里放xxx.shp、xxx.shx、xxx.dbf、xxx.prj然后使用 WinRAR 命令行rar a -r -ma5 -m5 -s -ep1 yantai_districts.rar yantai_shp_folder\-ma5指定 RAR 5 格式-m5是最大压缩率-s开启固实压缩模式-ep1排除根路径这样解压后直接得到区县文件夹。需要注意GIS 数据的 shp 配套文件必须放在同一个目录下且保持同名压缩时不要把.shp和.dbf分开到不同目录否则解压后软件加载会报错。Linux 环境如果安装了rar工具命令类似rar a -ma5 -m5 -s -r yantai_districts.rar /data/yantai_shp-r表示递归包含子目录。压缩时建议不要使用-p密码选项除非数据涉密。热词里“rar password cracker”和“16进制编辑器查看rar密码”也确实反映了部分人拿到的是加密 rar但这种操作首先不合法这篇文章不展开。5.2 为什么行政区划 shp 压缩率能达到 90% 以上RAR 对 shp 文件的压缩效果明显优于 ZIP主要原因是 RAR 5 格式对重复数据的检测能力更强且固实模式下能利用前面文件的数据匹配后续文件的重复块。区县级边界的坐标点往往在小数点后第 3 位才出现差异整数部分重复度极高。举个例子一条芝罘区北侧海岸线的坐标序列会反复落在121.40°E附近前 7 个字符完全相同这种结构非常适合字典类压缩算法。实际效果可以参考常见数据规模烟台 12 个区县的 polygon 边界坐标大约 5 万到 15 万个顶点SHP 原始体积约 3 到 8 MBRAR 固实压缩后通常在 200 到 800 KB 之间。而 ZIP 压缩率会差 5% 到 15%特别是在大量小文件同时压制时差距更明显。这个判断来自对多个版本公开区县边界数据的压缩测试具体数值因数据精度和顶点密度而异。5.3 解压后验证 SHP 没有在压缩过程中损坏的快速方法压缩和解压都有可能导致文件损坏尤其是从网上下载的 rar 包源文件本身可能就缺失某些配套文件。解压后推荐用两条命令验证第一条比较总文件数和大小第二条用ogrinfo直接读取# 检查解压目录里的文件完整性 ls -la yantai_districts\ # 逐一遍历所有 shp 并输出要素类型和数量 for f in yantai_districts/*.shp; do echo $f; ogrinfo -so $f -al | grep -E Feature Count|Geometry; doneogrinfo -so表示只读摘要不加载全部图形速度快且会抛出损坏提示。输出应该显示每个文件都有Feature Count和Geometry行。如果某个文件报错比如 “Unable to open datasource”说明压缩包里的这个 shp 不完整需要回到源文件重新压缩。提示检查 rar 压缩包本身可以使用rar t yantai_districts.rar命令t代表 test会逐文件校验 CRC不需要解压。6. 把边界数据同步成 2020 现势路网样式Web 可视化前必须处理的三个细节烟台各区县 shp 如果只是放在本机做空间分析前面几章已经够用。要把边界叠加到在线地图上比如 Mapbox、Leaflet、高德开放平台还需要额外处理三个细节这里用热词里的“2020全国道路shp下载”和“遥感道路shp文件”的思路把行政区划边界也纳入同一套发布链路里处理。第一个细节是属性字段名称必须改为英文字段互联网地图瓦片服务对中文属性字段的兼容性不佳所以发布前先做一次重命名字段操作。用 QGIS 的字段计算器逐个改效率低推荐直接在用 4.1 节的 Python 代码生成 shp 时就把字段名设计成code、name、pop这类短英文。第二个细节是输出格式推荐选择 GeoJSON 或 PMTiles而不是继续使用 shp。shp 格式没有 Web 标准直读方案浏览器无法直接加载需要后端解析后转成 GeoJSON 输出。热词“eps地图转为shp”也是基于同样的逻辑EPS 如果指的是某种地图导出格式转 shp 之后要发布到 Web 必须再转一次 GeoJSON所以这套链路里shp - GeoJSON - 前端渲染是固定搭配。GeoJSON 直接用ogr2ogr转换ogr2ogr -f GeoJSON yantai_counties.geojson yantai_counties_4547.shp第三步也是最容易被忽略的简化 geometry避免边界顶点过多导致前端卡顿。烟台边界 shp 中栖霞市和莱阳市这种面积大的区县高精度数据可能包含上千个顶点前端渲染时确实需要优化。用mapshaper命令行做简化最顺手mapshaper yantai_counties.geojson -simplify dp 15% -o yantai_counties_simplified.geojsondp表示 Douglas-Peucker 算法15%的含义不是保留 15% 的顶点数而是保留原始精度的 15%实际使用时根据缩放级别调整。城市级边界发布到全国尺度时用 5% 到 10% 都不会有明显视觉损失发布到市级底图建议不低于 30%。简化完后再用ogrinfo -so -al yantai_counties_simplified.geojson查看 Geography 列里的坐标精度如果发现坐标只保留到整数位说明简化参数过大需要回调到 25% 左右。另一个 Web 发布场景是把区县面转成“全国道路 2020 图层”的相交参考。比如你手里有 2020 年全国道路 shp 或遥感道路 shp想统计每个烟台区县的路网长度操作是先用 4.2 节把道路数据和区县边界统一到 EPSG:4547然后用 QGIS 的Intersection工具把道路线打断到区县边界上再用Length字段计算各区县内的道路总里程。命令行方案是ogr2ogr配合 SQL 执行空间连接但比较大的道路 shp 建议直接走 PostGIS否则 10 万条以上的线要素在本地 QGIS 里处理会明显卡顿。如果以2020全国道路shp下载这个检索词来找数据源拿到的道路数据多为 WGS84 经纬度和 CGCS2000 的边界叠加时会有几十米的偏移街道级别对这种偏移不敏感但区县尺度的面积统计和路网密度计算会受影响必须先做 4.2 节的投影转换再执行空间叠加。本文还有配套的精品资源点击获取
返回列表