ARTICLE DETAIL

资讯详情

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

海南省五级行政区划SHP数据实战:从加载校验到WKT导出与渔网分割

海南省五级行政区划SHP数据实战:从加载校验到WKT导出与渔网分割 简介本资源为2025年海南省五级行政区划矢量数据包面向GIS从业者、城乡规划研究人员、高校师生及需要开展空间分析的技术人员可解决省、市、县、乡镇街道、社区村界多层级地理数据获取难的问题。压缩包共38个文件约61.51MB以shp、shx、dbf、prj等Shapefile核心格式为主辅以sbx、sbn空间索引及cpg、xml元数据文件覆盖省、市、县、乡镇、村界五个层级可直接导入ArcGIS、QGIS等软件进行地图绘制与空间分析。目前已有460人学习下载。数据层级完整、边界精度较高适合用于宏观区域规划、土地利用分析、城乡扩张监测、灾害管理及基层精细化治理等场景也可作为科研论文、课程作业与商业选址分析的基础底图帮助读者快速搭建海南省地理空间研究的数据基础。1. 2025海南省五级行政区划SHP数据从村界到省界的矢量数据怎么落地拿到一份「海南省五级行政区划SHP数据」的需求通常不是单纯想收藏一个文件而是要在自己的系统里把省、市、县、乡镇、村这五级边界跑通。海南的行政区划比较特殊既有海口、三亚这类地级市又有省直辖的县级市和县还有大量乡镇和村界层级嵌套不像内陆省份那么规整。这份SHP矢量数据的价值在于它把五级边界统一到同一套坐标和属性结构里能直接用于地图渲染、空间统计、选址分析、渔网分割、导出WKT做接口校验等场景。适合做GIS开发、自然资源信息化、城乡规划、物流区划的从业者。下面按「数据长什么样 → 怎么加载和校验 → 怎么转换和分发 → 坑在哪」的顺序把可复现的路径讲清楚。2. 五级行政区划SHP数据的结构与字段设计先看懂再动手2.1 五级层级在属性表里怎么表达海南省五级行政区划SHP数据常见做法是每个层级一个独立的Shapefile或者合并成一个带层级字段的图层。独立文件的好处是加载快、字段干净合并图层的好处是做空间叠加时不用反复切换数据源。我一般会先确认拿到的是哪种组织方式。如果是独立文件目录里通常会出现类似hainan_province.shp、hainan_city.shp、hainan_county.shp、hainan_town.shp、hainan_village.shp这样的命名。每个文件对应一级属性表里至少要有行政区代码和名称两个字段。代码字段建议用字符串类型不要用数值类型因为行政区代码前几位可能以0开头数值类型会丢前导零。如果是合并图层属性表里会多出一个层级字段比如level或admin_level取值1到5分别对应省、市、县、乡镇、村。这种结构在做渔网分割或者按层级筛选时更方便一条SQL就能过滤出乡镇界。提示不管哪种组织方式先打开属性表看字段名和字段类型再决定后续处理脚本怎么写。字段名大小写不统一是常见问题ArcGIS和QGIS对大小写的敏感度不一样。2.2 坐标系与投影海南数据必须确认的一件事海南岛的经纬度范围大致在东经108°到111°、北纬18°到20°之间。如果拿到的是地理坐标系数据通常是CGCS2000或WGS84单位是度。如果要做面积统计、距离量算必须投影到平面坐标系否则算出来的面积是平方度没有意义。常见做法是投影到UTM 49N带或者用海南当地的省级投影。CGCS2000的EPSG代码是4490投影后的EPSG代码需要根据具体分带确定。我一般会在QGIS里先看图层属性里的CRS信息再用「测量工具」拉一条已知距离的线做校验。# 用geopandas检查SHP文件的坐标系和字段结构 import geopandas as gpd # 读取省级边界文件 gdf gpd.read_file(hainan_province.shp) # 打印坐标系信息 print(CRS:, gdf.crs) # 打印字段名和类型 print(Columns:, gdf.columns.tolist()) print(Dtypes:\n, gdf.dtypes) # 打印前3行属性 print(gdf.head(3)) # 检查几何类型是否统一 print(Geom types:, gdf.geom_type.unique())这段代码的逻辑是先确认坐标系再确认字段结构最后看几何类型。参数说明gpd.read_file直接读取SHP文件不需要额外驱动gdf.crs返回坐标系对象如果是None说明没有定义坐标系需要手动指定geom_type用来检查是否存在混合几何类型比如面和线混在一起这种情况在村界数据里偶尔出现会导致后续空间操作报错。如果发现坐标系是None可以用gdf.set_crs(epsg4490, inplaceTrue)补上。如果要做面积统计再用gdf.to_crs(epsg32649)投影到UTM 49N。2.3 用QGIS做一次可视化校验在写任何处理脚本之前我习惯先用QGIS把数据拖进去看一眼。重点看三件事边界有没有明显错位、村界有没有重叠或缝隙、属性表里有没有空名称。操作步骤打开QGIS把五个层级的SHP文件依次拖入图层面板右键每个图层选择「属性」→「源」确认坐标系一致用「识别要素」工具点击几个村界看属性表里的名称和代码是否完整最后打开「矢量」→「几何工具」→「检查有效性」看有没有自相交或空几何。如果发现村界之间有缝隙常见原因是数据采集时用了不同的底图或者做了简化处理。这种缝隙在做空间叠加时会变成空值区域需要用「融合」或「修复几何」处理。如果发现重叠通常是乡镇边界和村边界没有对齐需要以村界为准做一次更新。3. 把SHP用起来加载、筛选、导出WKT和渔网分割3.1 按层级筛选并导出乡镇和村界拿到五级数据后最常用的操作是按层级筛选。比如只想要乡镇界做人口统计或者只想要村界做电商配送范围。用geopandas可以一行代码完成筛选。import geopandas as gpd # 读取合并图层 gdf gpd.read_file(hainan_admin_all.shp) # 按层级字段筛选乡镇level4和村level5 town gdf[gdf[level] 4].copy() village gdf[gdf[level] 5].copy() # 检查筛选结果数量 print(乡镇数量:, len(town)) print(村数量:, len(village)) # 导出为新的SHP文件指定编码避免中文乱码 town.to_file(hainan_town_only.shp, encodingutf-8) village.to_file(hainan_village_only.shp, encodingutf-8)逻辑说明先读取合并图层再用布尔索引筛选。参数说明level字段名需要根据实际数据调整有的数据用admin_level或dijiencodingutf-8在导出时指定避免中文名称变成乱码ArcGIS打开时如果乱码可以在QGIS里重新导出并指定GBK编码。如果数据是独立文件直接读取对应的SHP即可不需要筛选。但要注意独立文件之间的行政区代码要能对应上否则做空间关联时会匹配失败。3.2 导出WKT用于接口校验和数据库入库很多业务系统不直接读SHP而是把边界转成WKT字符串存到数据库或传给前端。WKT的优点是纯文本、跨平台、容易做版本对比。从SHP导出WKT的常见做法是用geopandas的to_wkt()方法。import geopandas as gpd # 读取村界数据 village gpd.read_file(hainan_village_only.shp) # 确保坐标系是经纬度WKT通常用经纬度存储 village village.to_crs(epsg4490) # 生成WKT字段 village[wkt] village.geometry.to_wkt() # 导出为CSV只保留代码、名称和WKT village[[code, name, wkt]].to_csv( hainan_village_wkt.csv, indexFalse, encodingutf-8-sig ) # 打印一条WKT看格式 print(village[wkt].iloc[0][:200])逻辑说明先把坐标系转成经纬度因为WKT在数据库里通常按经纬度存储然后用to_wkt()生成字符串最后导出CSV。参数说明encodingutf-8-sig带BOM头Excel打开不乱码to_wkt()默认保留足够精度如果WKT太长可以用to_wkt(rounding_precision6)控制小数位数6位大约对应0.1米精度对行政区划足够。注意WKT字符串可能非常长一个复杂的村界WKT可能超过10万字符。入库前要确认数据库字段类型是TEXT或CLOB不要用VARCHAR(4000)。3.3 用渔网分割做格网统计渔网分割是行政区划数据的高频用法比如把海南岛切成1公里×1公里的格网统计每个格网落在哪个村或者计算每个格网内的道路密度。常见做法是用QGIS的「创建网格」工具或者用geopandas生成格网再做空间连接。import geopandas as gpd from shapely.geometry import box import numpy as np # 读取省级边界作为范围 province gpd.read_file(hainan_province.shp).to_crs(epsg32649) # 获取边界范围 minx, miny, maxx, maxy province.total_bounds # 生成1公里格网 cell_size 1000 # 单位米 cols np.arange(minx, maxx, cell_size) rows np.arange(miny, maxy, cell_size) # 构建格网几何 from shapely.geometry import Polygon grid_cells [] for x in cols: for y in rows: grid_cells.append(box(x, y, x cell_size, y cell_size)) grid gpd.GeoDataFrame(grid_cells, columns[geometry], crsEPSG:32649) # 只保留与海南岛相交的格网 grid gpd.overlay(grid, province, howintersection) # 与村界做空间连接统计每个格网所属的村 village gpd.read_file(hainan_village_only.shp).to_crs(epsg32649) joined gpd.sjoin(grid, village, howleft, predicateintersects) # 统计每个村的格网数量 count_by_village joined.groupby(name).size().reset_index(namegrid_count) print(count_by_village.head(10)) # 导出格网 grid.to_file(hainan_grid_1km.shp, encodingutf-8)逻辑说明先把省级边界投影到UTM获取范围然后按1公里步长生成格网用overlay裁剪到海南岛范围再用sjoin把格网和村界关联起来。参数说明cell_size可以根据需要改成500或2000predicateintersects表示格网与村界有交集就算关联如果只要完全落在村内的格网改成predicatewithingroupby(name)按村名统计如果村名有重复改用行政区代码字段。这个流程跑完后每个格网会带上所属村的属性可以进一步做人口、POI、道路的聚合统计。渔网分割的坑在于格网数量可能很大海南岛按1公里切大约有3万多个格网内存和计算时间要提前评估。4. 格式转换与跨工具协作DWG转SHP、SHP转TXT、SHP转3DTiles4.1 DWG转SHP的可行路径热搜词里出现「dwg转shp」说明很多人手里有CAD格式的区划图想转成SHP做GIS分析。DWG转SHP不是一键操作因为DWG是图层实体的结构SHP是要素类属性的结构。常见做法是先用QGIS或ArcGIS打开DWG把需要的图层导出为GeoJSON或DXF再转SHP。在QGIS里的步骤拖入DWG文件QGIS会提示选择图层勾选包含边界线的图层右键图层选择「导出」→「要素另存为」格式选ESRI Shapefile在导出对话框里指定坐标系如果DWG没有坐标系信息需要手动指定海南当地的投影导出后检查属性表DWG里的文字标注不会自动变成属性需要手动关联。如果DWG里的边界是闭合多段线导出后可能是线要素而不是面要素。需要先用「线转面」工具处理或者用「几何修复」把闭合线转成面。这个环节最容易翻车因为CAD里的线经常有微小缺口导致转面失败。4.2 SHP转TXT的两种用途「shp转txt」通常有两种需求一种是把坐标点导出成文本做外业核对另一种是把属性表导出成文本做数据交换。如果是坐标点可以用geopandas把几何的坐标序列写出来。import geopandas as gpd # 读取村界 village gpd.read_file(hainan_village_only.shp).to_crs(epsg4490) # 提取每个村的质心坐标 village[centroid] village.geometry.centroid village[lon] village[centroid].x village[lat] village[centroid].y # 导出为TXT制表符分隔 village[[code, name, lon, lat]].to_csv( hainan_village_centroid.txt, sep\t, indexFalse, encodingutf-8 )逻辑说明先投影到经纬度再算质心最后导出。参数说明sep\t是制表符分隔方便导入Excel或其他工具如果只要边界上的节点坐标可以用village.geometry.boundary再遍历坐标。如果是属性表导出直接用to_csv或to_excel即可注意中文字段用utf-8编码。4.3 SHP转3DTiles的适用场景「shp转3dtiles」一般出现在三维GIS项目里想把行政区划边界拉伸成体块在三维场景里做行政区划展示。这个转换不是标准GIS操作需要借助三维工具链。常见做法是先把SHP转成GeoJSON再用Cesium ion或开源工具做白模拉伸最后切成3DTiles。如果只是做边界线在三维场景里的贴地显示不需要转3DTiles直接把SHP转成GeoJSON用Cesium的GeoJsonDataSource加载即可。如果要做出有高度的行政区划体块需要给每个面一个高度字段再用工具做拉伸。这个流程对数据质量要求高面必须闭合且不能自相交否则拉伸会失败。提示SHP转3DTiles之前先用「检查有效性」工具修复几何确保每个面都是有效的。海南的村界数据如果来自不同来源几何质量参差不齐这一步不能省。5. 避坑与排查五级行政区划数据最常见的5个问题5.1 中文属性乱码现象是QGIS里名称显示正常ArcGIS里变成问号现象在QGIS里打开SHP村名显示正常用ArcGIS打开同一个文件中文全部变成乱码或问号。原因SHP文件的属性编码没有统一标准QGIS默认按UTF-8解析ArcGIS默认按系统编码解析。如果数据在导出时用了GBKArcGIS可能正常而QGIS乱码反之亦然。解决在QGIS里重新导出一次导出时在「编码」选项里明确选择UTF-8或GBK根据目标工具调整。如果要在两个工具之间来回用建议导出两份一份UTF-8给QGIS一份GBK给ArcGIS。或者把数据转成GeoPackage格式GeoPackage对编码的支持更统一。5.2 行政区代码前导零丢失现象是代码从「460100」变成「4601」现象属性表里的行政区代码字段原本是6位或9位打开后变成了数值前导零消失或者位数不对。原因SHP的DBF字段类型如果是数值型会丢失前导零。很多数据在生成时没有把代码字段设为字符串类型。解决用geopandas读取后把代码字段强制转成字符串再导出。如果已经丢失需要从原始数据重新导出或者在代码前补零。补零的逻辑要根据代码长度判断比如6位代码补到6位9位代码补到9位。import geopandas as gpd gdf gpd.read_file(hainan_admin.shp) # 强制转为字符串并补零到6位 gdf[code] gdf[code].astype(str).str.zfill(6) # 重新导出 gdf.to_file(hainan_admin_fixed.shp, encodingutf-8)5.3 村界与乡镇界不套合现象是村界超出乡镇界范围现象把村界和乡镇界叠加显示发现有些村界超出了所属乡镇的边界或者乡镇界内有空白区域没有村界覆盖。原因不同层级的数据来自不同采集批次或者做了不同的简化处理。村界可能用了更精细的底图乡镇界用了较粗的底图。解决以村界为准用「融合」工具按乡镇代码把村界合并成乡镇界替换原来的乡镇界。如果村界本身有缝隙先用「修复几何」处理。这个操作会改变乡镇界的形状需要和业务方确认是否可接受。5.4 投影不一致导致面积算错现象是面积统计结果差了几十倍现象用不同层级的SHP做面积统计省级面积和市县面积之和对不上或者面积数值明显偏大偏小。原因有的图层是地理坐标系单位度有的是投影坐标系单位米直接算面积会得到平方度或错误数值。解决统一投影到平面坐标系后再算面积。用gdf.crs检查每个图层的坐标系用to_crs统一转换。海南数据建议统一到EPSG:32649UTM 49N面积单位是平方米。5.5 渔网分割后格网数量爆炸现象是脚本跑了几十分钟还没结束现象用1公里格网分割海南岛脚本运行时间过长内存占用飙升。原因格网生成时用了整个边界框的范围包含了大量海域格网导致格网数量远超实际陆地面积所需。解决先用省级边界做overlay裁剪只保留与陆地相交的格网。或者先用clip把格网裁剪到陆地范围。另外格网尺寸不要设得太小1公里对村级统计通常够用500米会导致格网数量翻4倍。6. 进阶技巧用空间索引加速五级数据叠加以及一份可复用的校验清单五级行政区划数据用久了最耗时的操作不是加载而是反复做空间叠加。比如把村界和POI做空间连接或者把乡镇界和路网做叠加。数据量一大没有空间索引的叠加会慢到让人怀疑人生。我一般会在加载后立刻建空间索引geopandas底层用shapely可以调用sindex属性。import geopandas as gpd village gpd.read_file(hainan_village_only.shp).to_crs(epsg32649) poi gpd.read_file(hainan_poi.shp).to_crs(epsg32649) # 建空间索引 village.sindex poi.sindex # 用sjoin做空间连接底层会自动用索引 joined gpd.sjoin(poi, village, howleft, predicatewithin) # 统计每个村的POI数量 poi_count joined.groupby(name).size().reset_index(namepoi_count) print(poi_count.sort_values(poi_count, ascendingFalse).head(10))逻辑说明sindex是惰性构建的第一次访问时生成后续查询会复用。sjoin在底层会利用索引做候选筛选比暴力遍历快几个数量级。参数说明predicatewithin表示POI完全落在村界内才算如果只要相交就算改成intersects。对于海南这种数据量村界大约几千个POI可能几十万建索引后连接时间通常在秒级。另一个进阶用法是把五级数据做成层级树。每个村有唯一的行政区代码代码的前几位对应乡镇、县、市、省。可以用代码前缀做聚合不需要做空间叠加就能统计。比如村代码前6位是乡镇代码前4位是县级代码。这种编码规则在国标里是统一的用字符串切片就能实现层级汇总。import pandas as pd # 假设村数据里有9位行政区代码 village gpd.read_file(hainan_village_only.shp) # 提取乡镇代码前6位和县级代码前4位 village[town_code] village[code].str[:6] village[county_code] village[code].str[:4] # 按乡镇汇总村的数量 town_summary village.groupby(town_code).size().reset_index(namevillage_count) print(town_summary.head()) # 按县汇总 county_summary village.groupby(county_code).size().reset_index(namevillage_count) print(county_summary.head())这个方法的坑在于代码长度必须统一如果有的村代码是9位有的是12位切片会出错。先用str.len()检查代码长度分布再决定切片规则。最后给一份我每次拿到新行政区划数据都会跑的校验清单按顺序过一遍能避开大部分翻车检查项检查方法通过标准坐标系gdf.crs不为None且与业务需求一致几何类型gdf.geom_type.unique()只有Polygon或MultiPolygon空几何gdf.geometry.is_empty.sum()结果为0无效几何gdf.geometry.is_valid.all()结果为True代码长度gdf[code].str.len().unique()同一层级长度一致名称空值gdf[name].isna().sum()结果为0层级数量gdf[level].value_counts()与预期层级数一致这份清单跑完基本能确认数据可用。剩下的就是按业务需求做筛选、转换和叠加。我自己的习惯是每次拿到新数据先跑一遍这个清单把结果存成一个文本文件后面出问题可以回溯。希望帮到你。本文还有配套的精品资源点击获取
返回列表