☰
CGCS2000行政边界数据处理实战:从Shapefile到GeoPandas
2026/10/9 18:26:49 网站建设 项目流程

简介:2020年全国省、市、县三级行政边界矢量数据以rar压缩包形式整理发布,面向GIS开发者、测绘与城乡规划从业者、科研人员及地图制图爱好者,可直接用于地理空间分析、专题制图和区域统计。数据采用shp格式存储,并基于国家2000坐标系,坐标精度与统一性优于旧版北京54、西安80坐标系,适合作为底图叠加人口、经济等属性数据开展空间研究。压缩包共25个文件,以省、市、县三套shp核心数据及配套dbf属性表、prj投影信息、shx几何索引等文件为主,整体大小约62.23MB,目录层级简明,便于按行政级别调用。已有2257人学习下载,使用者在ArcGIS、QGIS等软件中可直接加载,快速提取省、市、县边界,完成缓冲区分析、叠置分析或专题制图;亦可结合统计年鉴开展人口密度、产业布局等空间分析,是2020年行政区划底图的高质量可复用资源。

1. 打开这个压缩包之前,先弄清楚它到底能做什么

做地图可视化、区域统计分析或者政务图层项目时,最烦的不是写代码,而是找一套干净、统一、能直接用坐标系图层。手头的数据要么是经纬度五花八门,要么是边界还是十几年前的旧版。这个 2020全国省、市、县行政边界-国家2000坐标系.rar 解决的就是这类问题:它把全国省、市、县三级行政区域的矢量边界整理成了一份相对规范的成果,统一落在国家2000坐标系(CGCS2000)下,拿到手不需要再做整体配准,直接进项目当底图或者做空间叠加分析。适合正在做 WebGIS、数据大屏、自然资源相关系统,或者需要把多个部门数据对齐到同一套地理基准的从业者。对你来说,最大的价值是省去从零开始收集和清洗行政区划数据的时间,同时少踩坐标基准不一致的坑。

2. 为什么行政区划数据偏偏要用国家2000坐标系:基准统一才是省心的前提

2.1 国家2000坐标系解决了什么历史问题

国家2000坐标系是我国现行法定的大地基准,缩写为CGCS2000。它的核心意义在于把过去分散在不同参考椭球下的测绘成果,收敛到一个统一、高精度、与国际地球参考框架衔接的坐标体系里。早些年很多地方数据用的是北京54或西安80,这类参心坐标系是建立在局部拟合基础上的,在跨省、跨大区域拼接时会产生明显裂缝和偏移。而CGCS2000属于地心坐标系,原点位于地球质心,对全国范围的数据整合更友好。

从这次 2020全国省、市、县行政边界-国家2000坐标系.rar 的标题看,发布者特意把坐标系写进文件名,就是在提醒使用者:这是一份以CGCS2000为基准的成果,解压后不需要再做七参数转换来与其他CGCS2000数据对齐。如果你过去习惯用WGS84坐标,需要知道两者在理论上很接近,但在实际生产里,同一地点的平面坐标差异通常在半米到几米之间,取决于当地转换参数和采集精度。

2.2 WGS84、GCJ02、BD09和CGCS2000的差异,决定你的叠加是否“肉眼可忍”

很多做前端地图的人会混淆几个概念。WGS84是全球卫星定位系统使用的协议地心坐标系,GPS直接输出的经纬度就是基于它的。GCJ02是我国测绘部门发布的一种加偏坐标系,俗称“火星坐标”,它跟WGS84之间不是简单的平移关系,而是非线性偏转。BD09则是某互联网地图品牌在GCJ02基础上再做二次加偏的产物。

如果这份数据被投放到网页底图上,必须搞清楚底图提供商采用的是哪一个坐标系。常见做法是,对互联网底图先判断其瓦片坐标规则,再进行投影或纠偏。我不建议在代码里对CGCS2000做“看起来差不多就行”的粗暴偏移,因为各省市的偏移量并不恒定,有的地方可能是几十米,有的地方可能大到百米级别。给空间数据做统一基准,是后续一切分析的先决条件。

2.3 一份边界数据该不该选CGCS2000,主要看这三个标准

面对一份来源不明的行政边界数据,可以用三个标准判断值不值得投入工程改造:第一,是否使用地心坐标系,这决定了跨区域拼接是否可靠;第二,是否有明确的现势性说明,2020版和2015版在局部边界上确实存在调整,标题里的年份就是参考锚点;第三,属性字段是否包含行政区代码与名称,这两项是后续关联业务数据的关键索引。这份数据在命名上占了前两项,具体字段质量则需要解压后验证。当前很多政务和测绘类项目,在项目设计中已经明确要求成果必须提交CGCS2000坐标,所以拿到这样一份数据,至少不会被基准问题卡住验收。

3. 拆开压缩包看门道:边界数据的组织方式与常见文件形态

3.1 压缩包里的文件构成与命名习惯

这类行政区划数据最常见的载体是Shapefile格式,它由多个同名不同后缀的文件组成,核心是.shp几何文件、.dbf属性表、.shx索引文件,以及配套的.prj坐标定义、.cpg字符集说明等。解压后你看到的可能是一个省一个文件夹,也可能所有县级面平铺在同一目录下。命名上常见形式是省/市/县代码加拼音或中文名,例如“110000_北京市”“320500_苏州市”这类组合。需要注意的是,有些包会额外附带一个.txt或.mxd工程说明文件,第一件事是打开它,确认数据的边界来源、更新年份、坐标基准和数学基础。

就这份2020标题的包来说,文件数量大概率在三千上下。县级边界是主体,省界和市界可能是独立图层,也可能是从县级面按属性融合派生出来的。拿到手先数一下是否有缺失,最简单的办法是统计.shp文件个数,如果明显少于预期县级数量,说明某些地级市或省直辖县的数据合并到了上一层,需要细看图层属性而非直接判断“缺数据”。

3.2 用桌面GIS软件快速验证,不要一上来就写代码

在动手写处理脚本之前,我建议你用桌面GIS软件做一次快速目检。打开软件,把.shp拖进视图,然后做三步检查:第一步,打开图层属性查看坐标系是否确实为CGCS2000;第二步,缩放带全国范围看整体轮廓是否完整,有没有明显飞地或零散破碎面;第三步,打开属性表看字段内容是否整齐,行政区代码是否为6位整数,名称是否混入繁体或拼音。这个流程五分钟内能完成,但能省掉后面代码调试的很多困惑。

3.3 属性表里的关键字段逐一拆解,别把代号当摆设

对这类行政区划数据,属性表里最值钱的字段是行政区代码和行政区名称。行政区代码通常为六位,前两位是省级,中间两位是地级,后两位是县级。例如某省某市某县的组合,在代码里能直接截取判断层级。常见字段还包括LVL或GRADE这类层级标识,用数字区分省、市、县;有的包还带AREA字段,但这个面积通常是投影平面坐标下的计算值,用于出图可以,用于法律意义上的面积认定则不一定准确。

如果你要做数据清洗,建议先把这些字段统一成标准命名,并做一次类型检查。很多包导出的.dbf里,数字字段被读成文本,或代码前导零被抹掉,导致关联业务表时匹配失败。我一般会在读取后立刻用astype把行政区代码转成字符串,再补零到6位,这是整套流程里最先要处理的基础问题。

4. 用脚本读取并整理这份边界数据:GeoPandas 的实用操作

4.1 读取数据的最小可行代码与运行前准备

你需要装好GeoPandas环境,建议使用专门的虚拟环境,避免与已有GIS工具冲突。下面是最小读取示例。

import geopandas as gpd from pathlib import Path # 假设解压后的县级面文件统一放在 counties 目录下 county_dir = Path("./counties") shp_files = list(county_dir.glob("*.shp")) print(f"共发现 {len(shp_files)} 个县级面文件") # 逐个读取并合并为一个GeoDataFrame,简化后面统一处理 gdf_list = [] for shp in shp_files: tmp = gpd.read_file(shp, encoding="utf-8") gdf_list.append(tmp) gdf = pd.concat(gdf_list, ignore_index=True) print(gdf.head())

这段代码的核心逻辑是遍历目录下的所有shapefile,分别读取后合并。参数encoding需要根据实际情况调整,有的包用GBK编码,有的用UTF-8,读出来中文乱码时优先尝试另一个。合并操作的ignore_index参数让索引重新排序。

4.2 按行政区代码层级做统计,验证数据覆盖度

拿到合并后的GeoDataFrame,下一步是统计各级数量,看看覆盖是否完整。

# 从6位行政区代码中截取省级和地级前缀 gdf["省代码"] = gdf["ADCODE"].str[:2] gdf["市代码"] = gdf["ADCODE"].str[:4] # 按省级代码统计县级数量 province_count = gdf.groupby("省代码").size().reset_index(name="县级数量") print(province_count)

这段统计的意义在于快速发现异常:每个省的县级数量应相对合理,如果某个省只有个位数,可能是合并或读取时出错了。参数上,str[:2]截取前两位作为省级代码,因为县级代码是六位,前两位就是省级标识。如果字段名不叫ADCODE,需要改成实际的名称。

4.3 从县级面聚合出市级和省级边界,并导出为GeoJSON

如果压缩包里没有现成的省级、市级面,可以用dissolve方法从县级面聚合出来。这是最稳妥的做法,能保证市界和省界与县界严格共边。

# 按市级代码聚合县级面,生成市级边界 city_gdf = gdf.dissolve(by="市代码", aggfunc="first").reset_index() # 再按省级代码聚合,生成省级边界 province_gdf = gdf.dissolve(by="省代码", aggfunc="first").reset_index() # 导出为GeoJSON,方便后续前端加载 province_gdf.to_file("province.geojson", driver="GeoJSON", encoding="utf-8")

dissolve是GeoPandas里非常实用的几何融合操作,它的by参数指定按哪个字段分组。aggfunc="first"表示对非几何字段取第一条记录,避免属性列合并报错。导出GeoJSON时指定编码,防止中文属性在浏览器端乱码。如果你只需要某一层,可以只做对应层级的dissolve,节省处理时间。

4.4 给数据统一重设坐标系,避免交付时基准不一致

有些包解压后.prj文件缺失或写得不规范,导致GeoPandas读出来坐标系为空。这种情况下,即便几何坐标本身是CGCS2000,也无法参与空间叠加。处理方式是手动指定坐标系。

from pyproj import CRS crs_cgcs2000 = CRS.from_epsg(4490) if gdf.crs is None: gdf = gdf.set_crs(crs_cgcs2000) else: gdf = gdf.to_crs(crs_cgcs2000)

EPSG:4490是CGCS2000地理坐标系的标准编码。如果数据本身使用高斯投影或UTM投影,你需要先确认其投影带,再做投影转换。set_crs和to_crs的区别在于前者只是声明坐标系,不改变坐标值,后者是真正的坐标转换。对于完整度高的数据,这里通常只需要声明。

5. 避坑指南:处理行政边界数据最容易翻车的5个细节

5.1 现象:属性表里中文全部变成乱码或问号

原因:Shapefile的.dbf属性默认编码可能是GBK或GB2312,GeoPandas和部分桌面软件默认按UTF-8读取,导致中文显示异常。这是一个高频问题,尤其是从国内渠道获取的数据包里很常见。解决方法是先尝试用encoding="gbk"重新读取,如果字段里仍有少量乱码,再用encoding="gb18030"。如果数据本身混入了繁体或异体字,需要额外做字符规范化。最省事的思路是读入后统一转成UTF-8并另存为新文件,后续所有流程都基于清洗后的副本,原包保持不动作为备份。

5.2 现象:相邻县界的公共边界会有细小缝隙或重叠

原因:行政区划数据在数字化过程中,如果相邻县分别采集,没有做严格的公共边一致化处理,就会出现拓扑不一致。缝隙和重叠面积一般非常小,肉眼难察觉,但做面积统计或叠加分析时会误差放大。解决方法是做一个全局拓扑检查,找到缝隙和重叠的地理位置,然后用union或者snap操作统一处理。对于多数项目而言,最简单实用的做法是保留县级面,不要轻易把多个县的几何合并后再切割,因为合并操作会放大原有拓扑问题。如果只是出图展示,略微的缝隙无伤大雅;如果是统计用途,建议先做拓扑修复再入库。

5.3 现象:和互联网底图叠加时,边界偏移几十米到上百米

原因:互联网地图服务常用GCJ02坐标系,和CGCS2000存在非线性加偏,直接用经纬度叠加必然偏移。解决方法是确定底图供应商的坐标系类型,如果底图是GCJ02,就需要把我们的数据从CGCS2000先转成GCJ02。市面上有很多封装好的坐标转换库可供参考,但不建议对所有点做批量“概略转换”,因为在不同区域误差不一致。最稳妥的方案是找到底图的官方转换服务或工具,如果没有,就接受“精度不高、定位可用”的结果,并在文档中说明坐标偏移不确定度。

5.4 现象:省级边界文件里包含了海域界线,叠加后出现大片海面填充

原因:部分行政区划数据在制作时会把领海线或海域界线纳入省级面,导致海陆渲染时整个海面被涂成省份颜色。解决方法是区分陆地边界和海域边界这两个概念,在出图时对海域部分单独处理。常见做法是裁掉低纬度海域范围,或者用专用的海岸线数据作为裁剪掩膜。需要注意的是,不要轻易删除属性表里的记录,因为海域界线在部分业务场景中具有管理意义,错误删除会影响后续海洋相关分析。

5.5 现象:数据放大到乡镇街道级别时,边界出现锯齿和尖角

原因:原始数据比例尺有限,边界精度并不能支撑大比例尺缩放。某些县级边界在1:5万比例尺下显示正常,放大到1:1万时锯齿明显。解决方法是引入简化工具如shapely的simplify,设置合适的容差后输出用于大比例尺出图的简化版本。需要强调的是,简化会损失精度,只适合可视化展示,不适合用于边界仲裁或精确面积计算。建议在交付物中同时保留原始精度数据和简化数据两个版本,避免后续返工。

6. 让这份数据真正成为稳定交付物:一套可复用的自检与清洗脚本

6.1 构建行政区数据可用性体检报告

与其每次拿到新数据都靠肉眼和手工检查,不如直接跑一套体检脚本,从属性完整性、几何有效性和拓扑关系三个维度输出报告。下面是我常用的一段体检逻辑。

import geopandas as gpd import numpy as np # 读取合并后的gdf,这里假定已经是清洗过的副本 gdf = gpd.read_file("county_merged.shp", encoding="utf-8") # 检查属性完整性:行政区代码和名称是否有空值 missing_code = gdf["ADCODE"].isna().sum() missing_name = gdf["NAME"].isna().sum() print(f"缺失行政区代码记录数: {missing_code}") print(f"缺失行政区名称记录数: {missing_name}") # 检查几何有效性:排除自相交、空几何等问题 valid_mask = gdf.geometry.is_valid invalid_count = (~valid_mask).sum() print(f"无效几何数量: {invalid_count}") # 检查是否有重叠面,这个操作相对耗时,建议抽样或分省执行 overlap_pairs = [] for i in range(len(gdf)): for j in range(i+1, len(gdf)): if gdf.geometry.iloc[i].intersects(gdf.geometry.iloc[j]): overlap_pairs.append((i, j)) print(f"检测到重叠面数量: {len(overlap_pairs)}") # 输出体检汇总 report = { "总记录数": len(gdf), "缺失代码": missing_code, "缺失名称": missing_name, "无效几何": int(invalid_count), "重叠面对数": len(overlap_pairs), } print(report)

这段代码有三个关键参数需要关注:is_valid是shapely提供的几何有效性检查,它能够识别自相交环、空几何等常见问题,但不会自动修复,通常需要结合buffer(0)来做轻量修复。intersects做的是两两相交判断,在记录数上万时性能会变得很差,所以生产环境里我会先用空间索引或按省分组来缩小比较范围,而不是全量双重循环。

6.2 清洗完数据之后,建议形成的三个交付物

不要把清洗过程当成一次性动作。我习惯在项目里固定生成三个版本:原始备份版、清洗可用版、精简出图版。原始备份版保留解压后的所有文件,不做任何改动,用于回溯对比。清洗可用版完成坐标声明、属性类型修正、无效几何修复,并输出为GeoPackage或Shapefile,供业务系统调用。精简出图版则在清洗版基础上做边界简化,去掉微观锯齿,适合Web端渲染和专题图出图。三个版本的坐标系全部统一标注为CGCS2000,避免后续用错。

6.3 边界数据的长期更新策略与月度检查

行政区划不是一成不变的,撤县设区、乡镇合并、村级调整都会让旧版本的边界逐渐失效。我的习惯是把这份2020版数据作为基线,在系统里记录数据的发布时间和来源类型,并每年做一次与权威发布的对比。检测方法并不复杂:打开最新数据,与基线做一次overlay差分分析,找出几何变化的区域,再人工确认变化类型是边界微调还是区划调整。这种做法能帮助你在业务中提前感知哪些区域的统计结果可能受边界影响。

我在实际项目中就遇到过因为边界变化导致统计报表对不上的情况。当时某区域的GDP对比分析前后差了数个点,追查下来才发现一个县级边界在上一年度进行了调整。从那以后,凡是涉及跨年对比的分析,我都会在SQL里加一个“基期边界”的过滤条件,先锁定几何版本,再跑聚合,比事后解释数据变化原因省力得多。这一条经验也算是我做空间数据工作多年血泪总结里最值得分享的一条。

如果你只是短期用一次,2020版数据足够应付多数展示和基础分析场景;如果你要做持续运营的GIS系统,建议把这套数据当成“基础底图”而非“永久底图”,在系统说明里注明数据现势性,这样就不会让使用方产生过时边界还能用于精确决策的误解。希望这份整理能帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询