资讯动态

2025海南省五级行政区划SHP数据:从省到村界的空间统计与转换实战

发布时间:2026/10/26 19:08:34 来源:尧图企业网站定制
简介本资源为2025年海南省五级行政区划矢量数据包面向从事GIS空间分析、城乡规划、资源管理与地理研究的科研人员、政府决策者及高校师生可解决省、市、县、乡镇街道、社区村界多层级地理数据获取难的问题。压缩包共38个文件约61.51MB以shp、shx、dbf、prj等Shapefile核心格式为主辅以sbx、sbn空间索引及cpg、xml元数据文件覆盖省、市、县、乡镇、村界五个层级可直接在ArcGIS、QGIS等软件中加载、绘制地图并开展空间分析。目前已有460人学习下载。数据层级完整、边界精度较高适合用于宏观区域规划、土地利用分析、城乡扩张监测、灾害管理与基层精细化治理等场景也可作为GIS教学与项目实践的基础底图帮助读者快速构建海南省多尺度空间分析框架。1. 从一份海南五级区划 SHP 说起省到村界到底能拿来干什么前阵子帮一个做农业遥感的朋友处理地块数据他手里有海南全省的作物分布栅格想按行政村统计种植面积结果卡在最后一步——找不到带村界这一级的矢量底图。网上能搜到的海南行政区划数据大多只到市县少数到乡镇村界这一级要么缺失要么属性字段残缺要么坐标系对不上。后来翻到这份 2025 海南省五级行政区划 SHP 数据省、市、县、乡镇、村界五级齐全才算把统计链路跑通。这份资源的核心价值在于「层级完整」和「属性可用」。五级区划意味着你可以从省级一路下钻到村界做多尺度的空间统计、制图或空间连接。适合做国土空间规划、农业估产、物流网点选址、应急资源调度这类需要精细行政单元的场景。如果你只是画个海南省轮廓图那用不上它但只要涉及「按村汇总」「按乡镇裁剪」「按市县做空间查询」这份数据就是底图级别的存在。SHP 格式虽然老但兼容性极强ArcGIS、QGIS、GeoPandas、PostGIS 都能直接吃进去这也是它至今仍是矢量数据交换主流格式的原因。2. 五级区划 SHP 的字段结构与坐标系拿到数据先别急着加载2.1 五级图层拆分的逻辑与属性字段含义这份数据按行政级别拆成五个独立图层常见做法是省、市、县、乡镇、村界各一个.shp文件配套.dbf、.shx、.prj等。每个图层的属性表里核心字段通常包括行政区代码、名称、上级代码、几何类型。村界图层的字段最值得关注因为它直接决定你能不能和外部数据做关联。我一般拿到数据后先做三件事看.prj确认坐标系看.dbf字段类型和长度看几何是否有多部件或自相交。村界数据因为采集精度问题容易出现飞地、缝隙、重叠这些在后续空间连接时都是坑。属性字段里行政区代码是关联外部数据的钥匙但要注意它可能是字符串型也可能是数值型数值型会丢前导零这是血泪经验。图层常见字段字段类型注意点典型用途省界省代码、省名称代码 2 位全省制图、宏观统计市界市代码、市名称、省代码代码 4 位地级市汇总县界县代码、县名称、市代码代码 6 位县域分析乡镇乡镇代码、名称、县代码代码 9 位乡镇级统计村界村代码、名称、乡镇代码代码 12 位村级精细统计2.2 坐标系识别与投影转换的实操步骤坐标系是矢量数据的第一道门槛。这份海南数据常见的是 CGCS2000 地理坐标系EPSG:4490或 WGS84EPSG:4326也可能带投影坐标系如 CGCS2000 3 度带。如果.prj文件缺失或乱码可以用 QGIS 或 GeoPandas 读取后查看 CRS。import geopandas as gpd # 读取村界图层先看坐标系和字段 village gpd.read_file(hainan_village.shp) print(CRS:, village.crs) print(字段:, village.columns.tolist()) print(几何类型:, village.geom_type.unique()) print(前 3 行:\n, village.head(3)) # 如果 CRS 为空手动指定为 CGCS2000 地理坐标系 if village.crs is None: village village.set_crs(epsg4490) # 做面积统计前必须投影到等面积坐标系否则面积单位是度没有意义 village_proj village.to_crs(epsg4527) # CGCS2000 3 度带海南适用 village_proj[area_km2] village_proj.geometry.area / 1e6 print(village_proj[[村名称, area_km2]].head())这段代码的逻辑是先读取并检查 CRS缺失时手动指定然后投影到等面积坐标系再算面积。参数上EPSG:4490 是 CGCS2000 地理坐标EPSG:4527 是 CGCS2000 3 度带投影海南大致在 108°E 到 111°E 之间3 度带带号对应 EPSG:4525 到 4528 区间具体带号要看数据实际经度范围。如果投影带选错面积会有系统性偏差这个坑在跨带数据里特别常见。提示不要在地理坐标系下直接算面积或做缓冲区单位是度结果没有物理意义。先投影再计算。3. 用 GeoPandas 做村级空间统计从加载到汇总的完整链路3.1 空间连接与分组统计的代码实现拿到五级区划后最常见的操作是把外部点数据或栅格统计值挂到村界上。假设你有一份农户采样点 CSV带经纬度想统计每个村的采样点数量核心就是空间连接加分组计数。import pandas as pd import geopandas as gpd from shapely.geometry import Point # 读取村界并投影到适合的坐标系 village gpd.read_file(hainan_village.shp).to_crs(epsg4527) # 读取采样点 CSV构造几何列 df pd.read_csv(samples.csv) geometry [Point(xy) for xy in zip(df[经度], df[纬度])] points gpd.GeoDataFrame(df, geometrygeometry, crsEPSG:4326).to_crs(epsg4527) # 空间连接每个点落在哪个村 joined gpd.sjoin(points, village, howleft, predicatewithin) # 按村分组计数 count_by_village joined.groupby(村代码).size().reset_index(name采样点数) print(count_by_village.head()) # 把统计结果挂回村界属性表 village_stats village.merge(count_by_village, on村代码, howleft) village_stats[采样点数] village_stats[采样点数].fillna(0) village_stats.to_file(village_with_stats.shp, encodingutf-8)逻辑说明sjoin的predicatewithin表示点必须完全落在村界多边形内部边界上的点可能被漏掉这是常见争议点。参数上howleft保留所有点没匹配上的村代码为空。分组计数后merge回村界fillna(0)把没有采样点的村补零。最后导出时指定encodingutf-8否则中文属性在 ArcGIS 里可能乱码。3.2 多级汇总与面积加权计算村级统计做完后往往需要向上汇总到乡镇、县、市。如果只是简单求和直接按上级代码分组即可但如果涉及密度、比例这类指标就需要面积加权。# 从村界汇总到乡镇先按乡镇代码分组求和 town_stats village_stats.dissolve(by乡镇代码, aggfunc{ 采样点数: sum, area_km2: sum }).reset_index() # 计算乡镇级采样密度 town_stats[采样密度] town_stats[采样点数] / town_stats[area_km2] # 继续汇总到县级 county_stats town_stats.dissolve(by县代码, aggfunc{ 采样点数: sum, area_km2: sum }).reset_index() county_stats[采样密度] county_stats[采样点数] / county_stats[area_km2] print(county_stats[[县代码, 采样点数, area_km2, 采样密度]])dissolve是 GeoPandas 里做行政层级汇总的核心方法它按指定字段合并几何并聚合属性。参数aggfunc决定各字段的聚合方式计数类用sum面积类也用sum密度类必须重新计算而不是直接平均。这里有个容易翻车的地方如果村界之间有重叠dissolve后的面积会偏大导致密度偏低。所以做汇总前最好先检查几何有效性。注意dissolve前建议执行village_stats village_stats[village_stats.is_valid]剔除无效几何否则合并结果可能异常。4. 避坑与排查五级区划 SHP 使用中的五个真实翻车记录4.1 中文属性乱码现象、原因与解决现象用 ArcGIS 打开 SHP属性表里村名称显示为乱码或问号。原因.dbf文件的默认编码是 GBK 或 GB2312而 QGIS 或 GeoPandas 默认按 UTF-8 读取。解决在 QGIS 里设置图层编码为 GBK或用 GeoPandas 读取时指定encodinggbk导出时统一转成 UTF-8。我一般会在第一次读取后立刻另存为 UTF-8 版本后续都用这个版本。4.2 村界几何自相交与缝隙现象、原因与解决现象做空间连接时某些点明明在村界内却匹配不上或者一个点匹配到多个村。原因村界多边形存在自相交、缝隙或重叠常见于不同来源数据拼接处。解决用village.geometry.is_valid检查对无效几何执行buffer(0)修复对重叠区域用dissolve合并或按优先级去重。缝隙问题可以用snap或小缓冲容差处理但容差不能太大否则会改变边界。4.3 坐标系误判导致面积偏差现象、原因与解决现象算出来的村面积和官方公布数据差几倍。原因把地理坐标系当成投影坐标系直接算面积或者投影带选错。解决先确认.prj内容再用to_crs转到对应 3 度带或 6 度带。海南跨 109°E 到 111°E3 度带带号 37 对应中央经线 111°EEPSG 约 4527。如果数据跨带需要分带处理或统一到 Albers 等面积投影。4.4 行政区代码前导零丢失现象、原因与解决现象村代码从 12 位变成 11 位或更少和外部数据关联不上。原因.dbf里代码字段是数值型读取时前导零被自动去掉。解决读取时用dtype{村代码: str}强制字符串或者在 Excel 里先把列格式设为文本再导入。如果已经丢了可以用zfill(12)补零但前提是知道原始位数。4.5 导出 GeoJSON 后中文变 Unicode 转义现象、原因与解决现象SHP 转 GeoJSON 后用文本编辑器打开中文变成\uXXXX。原因GeoJSON 规范默认用 Unicode 转义不是乱码。解决用to_file(..., driverGeoJSON)时加encodingutf-8或者用json.dumps(..., ensure_asciiFalse)重新序列化。这个不算错误但影响可读性做 Web 地图时浏览器能正常解析。5. 从 SHP 到 3D Tiles 与 WKT几个高频转换场景的实操参数5.1 SHP 转 3D Tiles 的预处理与工具链村界数据做三维可视化时常见需求是转成 3D Tiles 在 Cesium 里加载。SHP 不能直接转 3D Tiles中间需要经过 GeoJSON 或 CityGML。我一般用ogr2ogr先转 GeoJSON再用3d-tiles-tools或Cesium ion做切片。# 第一步SHP 转 GeoJSON指定坐标系和编码 ogr2ogr -f GeoJSON -t_srs EPSG:4326 -lco ENCODINGUTF-8 village.geojson hainan_village.shp # 第二步用 3d-tiles-tools 做切片需先安装 Node.js 环境 npx 3d-tiles-tools createTileset -i village.geojson -o ./tileset --format b3dm参数说明-t_srs EPSG:4326把数据转到 WGS84 地理坐标这是 Cesium 的默认坐标系。-lco ENCODINGUTF-8保证中文属性不乱码。切片时--format b3dm是 Batched 3D Model适合带属性的矢量面。如果村界数据量很大建议先按市县拆分再切片否则单个 tileset 可能过大加载卡顿。5.2 SHP 转 WKT 与 TXT 的批量导出有些数据库或接口只接受 WKT 格式的几何字符串比如 PostGIS 的ST_GeomFromText。把 SHP 批量转 WKT 并导出 TXT可以用 GeoPandas 一行搞定。import geopandas as gpd village gpd.read_file(hainan_village.shp, encodinggbk) village[wkt] village.geometry.apply(lambda g: g.wkt) # 导出村代码、名称、WKT 到 TXT village[[村代码, 村名称, wkt]].to_csv(village_wkt.txt, sep\t, indexFalse, encodingutf-8) print(导出完成共, len(village), 条)逻辑说明g.wkt把 Shapely 几何对象转成 WKT 字符串to_csv用制表符分隔方便后续导入数据库。参数上sep\t避免 WKT 里的逗号和 CSV 分隔符冲突。如果 WKT 太长某些数据库字段长度不够需要先简化几何或改用 WKB。5.3 渔网分割与村界裁剪的配合使用做空间抽样或格网统计时常需要生成渔网再和村界叠加。渔网分割 SHP 的常见做法是用 QGIS 的「创建网格」工具或者用 GeoPandas 生成规则格网再裁剪。import numpy as np from shapely.geometry import box # 获取村界范围 minx, miny, maxx, maxy village.total_bounds cell_size 1000 # 1km 格网 # 生成格网 cols list(np.arange(minx, maxx, cell_size)) rows list(np.arange(miny, maxy, cell_size)) cells [box(x, y, x cell_size, y cell_size) for x in cols for y in rows] grid gpd.GeoDataFrame({geometry: cells}, crsvillage.crs) # 用村界裁剪格网 grid_clipped gpd.overlay(grid, village, howintersection) print(裁剪后格网数:, len(grid_clipped))参数说明cell_size单位是米因为已经投影到等面积坐标系。overlay的howintersection保留格网和村界的交集每个格网会带上所在村的属性。如果格网太密内存会爆建议分县处理。提示渔网分割前务必确认投影坐标系地理坐标系下cell_size单位是度1 度约 111 公里格网会大得离谱。6. 验证数据完整性与批量处理的几个习惯6.1 用拓扑检查验证五级区划的层级一致性拿到五级数据后我习惯先做一轮拓扑验证村界合并后是否等于乡镇边界乡镇合并后是否等于县界以此类推。如果某一级合并后和上一级对不上说明数据有缝隙或重叠。# 村界合并后与乡镇边界对比面积 village_dissolved village.dissolve(by乡镇代码) town gpd.read_file(hainan_town.shp).to_crs(village.crs) # 计算面积差异 village_dissolved[area_v] village_dissolved.geometry.area town[area_t] town.geometry.area compare village_dissolved.merge(town[[乡镇代码, area_t]], on乡镇代码) compare[diff_ratio] abs(compare[area_v] - compare[area_t]) / compare[area_t] print(compare[compare[diff_ratio] 0.01][[乡镇代码, diff_ratio]])这段代码找出面积差异超过 1% 的乡镇这些就是需要重点检查的区域。差异可能来自坐标系不一致、几何精度损失或数据版本不匹配。我一般会把差异大的乡镇单独导出在 QGIS 里叠加查看确认是缝隙还是重叠。6.2 批量裁剪与分县导出的脚本模板如果只需要某个市县的数据批量裁剪比手动选择高效得多。下面这个模板按县代码循环每个县导出一个 SHP。import os county_list village[县代码].unique() os.makedirs(output_by_county, exist_okTrue) for code in county_list: subset village[village[县代码] code] out_path foutput_by_county/{code}_village.shp subset.to_file(out_path, encodingutf-8) print(f导出 {code}: {len(subset)} 个村)逻辑说明按县代码分组导出文件名带县代码方便索引。参数上encodingutf-8保证中文正常。如果数据量大可以加chunksize或改用 GeoPackage 格式避免 SHP 的 2GB 单文件限制。6.3 一个让我改掉坏习惯的教训早期我做村级统计时直接拿地理坐标系的数据算面积结果全县总面积比官方数据大了将近 30 倍排查了一下午才发现是单位问题。从那以后我每次拿到任何 SHP 数据第一件事就是print(gdf.crs)第二件事是to_crs到等面积投影第三件事才是打开属性表看字段。这个顺序帮我省掉了至少十次返工。希望这份海南五级区划数据和上面的处理思路能帮你把村级尺度的空间分析链路一次跑通。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑