ARTICLE DETAIL

资讯详情

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

中国河流三级流域范围CGCS2000数据实战:从裁剪到分区统计

中国河流三级流域范围CGCS2000数据实战:从裁剪到分区统计 简介这份资源提供中国河流三级流域范围的完整GIS矢量数据采用CGCS2000国家大地坐标系面向水文研究、水资源管理、环境规划及地理信息分析等领域的从业者与学习者。压缩包共7个文件约2.58MB以ESRI Shapefile格式为主包含shp几何边界、shx与sbn/sbx空间索引、dbf属性表、prj投影定义以及shp.xml元数据各文件协同支撑流域边界的存储、检索与坐标描述。目前已有823人学习下载。数据可直接导入ArcGIS或QGIS用于空间分析、专题制图及与其它地理图层叠加帮助读者掌握中国三级流域的分布特征与层级关系为水文建模、资源区划和灾害预防提供基础底图支撑。1. 拿到一份三级流域数据先别急着往 ArcGIS 里拖做水文、防洪、水环境容量核算的人迟早会碰到一个尴尬手上有全国河流的线数据也有省界、市界但真正要算某个断面以上的汇水范围时发现缺一层能把大江大河拆到可操作粒度的面数据。中国河流三级流域范围 CGCS2000 就是补这个缺口的——它把全国流域按一级、二级、三级逐层切分每个多边形带自己的编码和名称坐标系是 CGCS2000。这意味着你拿到手就能直接和 CGCS2000 的 DEM、行政区划、监测点位做叠加不用先折腾一遍坐标转换。它适合三类人做流域面源污染负荷估算的、做洪水风险图需要划分子汇水单元的、做水资源规划要把统计口径落到具体流域的。不适合只想看个全国水系示意图的人——那份数据对你来说太重了。真正要留意的是三级流域的划分逻辑它不是按行政区走的一个三级流域可能横跨两三个地级市所以拿它和行政区做统计关联时得先想清楚是「按面积占比分摊」还是「按主导流域归属」。2. 三级流域的编码体系与 CGCS2000 坐标到底意味着什么2.1 一级、二级、三级是怎么切出来的全国流域划分通常遵循「大流域 → 支流区间 → 控制单元」的层级。一级流域对应长江、黄河、珠江、松花江、辽河、海河、淮河、东南诸河、西南诸河、西北诸河这十大片区二级流域是在一级内部按主要支流或河段进一步拆分比如长江上游、长江中游、长江下游三级流域则落到更小的控制区间往往对应一条支流的中下游或一个相对独立的汇水单元。这套层级的关键在于编码。常见做法是用固定位数的数字串表示层级关系前几位标识一级中间几位标识二级末几位标识三级。这样你在数据库里可以直接用LEFT(code, 2)或SUBSTRING把任意一级聚合出来不用额外维护一张父子关系表。我一般会先确认编码位数规则再决定用字符串截取还是建递归查询。提示不同来源的流域编码位数可能不一样拿到数据第一件事是看字段长度分布别默认全国都是同一套规则。2.2 CGCS2000 在流域数据里为什么重要CGCS2000 是当前国内测绘和地理信息数据的主流大地基准。它的椭球参数和 WGS84 非常接近但在严格意义上并不等同。对于流域这种大范围面数据如果基准不统一叠加时会出现几十米到上百米的偏移——在省级尺度上看着无所谓但你要算的是某个断面以上的精确汇水面积这个偏移就可能让边界处的栅格统计差出几个百分点。常见做法是确认数据的坐标参考是地理坐标经纬度还是投影坐标比如 CGCS2000 3 度带高斯投影。如果是经纬度面积计算前必须先投影否则算出来的「平方度」没有物理意义。我一般会在 ArcGIS 或 QGIS 里先看图层属性的 CRS 描述再用「投影」工具转成以米为单位的投影坐标系之后所有面积、长度计算才可信。2.3 属性表里该看哪些字段一份能用的三级流域面数据属性表至少要有三级流域编码、三级流域名称、所属二级流域编码、所属一级流域编码。有些版本还会带面积字段和备注。拿到之后先做三件事检查编码字段是否有重复或空值重复往往意味着几何被拆成了多部件检查名称字段有没有乱码尤其是从 Shapefile 转过来的时候DBF 的编码问题很常见用「几何修复」跑一遍看有没有自相交或环方向错误。import geopandas as gpd gdf gpd.read_file(china_basin_l3.shp, encodingutf-8) print(gdf.crs) # 确认坐标系 print(gdf.columns.tolist()) # 看字段名 print(gdf[L3_CODE].duplicated().sum())# 编码重复数 print(gdf.geometry.is_valid.all()) # 几何是否全部有效这段代码做的是数据体检。crs告诉你当前基准和投影方式duplicated().sum()返回重复编码数量大于 0 就得查是不是多部件几何is_valid为 False 时后续叠加分析可能直接报错需要先gdf.geometry gdf.geometry.buffer(0)做一次修复。注意buffer(0)是常见修复手段但对特别复杂的自相交不一定彻底必要时用make_valid。3. 把三级流域接进你的分析流程从裁剪到面积统计3.1 按研究区裁剪出需要的三级流域全国数据直接加载会很卡尤其在做栅格统计时。第一步永远是按研究区范围裁剪。假设你有一个省界或市界的面文件想取出落在里面的三级流域import geopandas as gpd basin gpd.read_file(china_basin_l3.shp) study gpd.read_file(study_area.shp) # 统一坐标系后再裁剪 study study.to_crs(basin.crs) clipped gpd.overlay(basin, study, howintersection) clipped.to_file(basin_l3_clip.shp, encodingutf-8)to_crs保证两个图层基准一致这是避免「裁剪结果为空」最常见的原因。overlay的howintersection表示取交集得到的是被研究区边界切开后的流域多边形。注意切开之后一个三级流域可能变成多个碎片但编码还是同一个——后面做统计时要按编码聚合不能按要素条数算。3.2 用分区统计把栅格值落到每个三级流域这是三级流域数据最核心的用法你有一张降雨栅格、NDVI 栅格或污染负荷栅格想按流域汇总。ArcGIS 里用「分区统计」Zonal Statistics as TableQGIS 里可以用「分区统计」或 Python 的rasterstats。from rasterstats import zonal_stats stats zonal_stats( basin_l3_clip.shp, rainfall_2023.tif, stats[mean, sum, count], geojson_outTrue ) for f in stats: print(f[properties][L3_CODE], f[properties][mean])stats参数决定输出哪些统计量mean适合看平均降雨sum适合看总量但要注意栅格分辨率——分辨率越粗sum越不可靠。geojson_outTrue让结果直接带属性方便后续写回。这里最容易翻车的是栅格和矢量坐标系不一致rasterstats不会自动帮你转得先手动对齐。3.3 面积计算先投影再算别偷懒流域面积是很多分析的分母。地理坐标系下直接算面积得到的是球面度不是平方米。正确做法是先投影到等面积投影或高斯投影basin_proj clipped.to_crs(EPSG:4547) # CGCS2000 3度带中央经线117E basin_proj[area_km2] basin_proj.geometry.area / 1e6 print(basin_proj[[L3_CODE, area_km2]].head())EPSG:4547是 CGCS2000 3 度带第 39 带适用于 117°E 附近。如果你研究区跨带就得按带分别投影再合并或者直接用 Albers 等面积投影。/1e6是把平方米转成平方公里。这一步没有捷径投影选错面积能差出百分之几后面所有负荷核算全跟着偏。4. 避坑与排查三级流域数据落地时最容易翻车的五件事4.1 现象裁剪结果为空或只剩零星几个多边形原因两个图层坐标系不一致或者研究区边界和流域边界根本没有重叠。很多人以为 ArcGIS 会自动投影对齐实际上Clip工具在坐标系不同时会直接按坐标数值硬算结果自然不对。解决裁剪前统一用to_crs或「投影」工具把两个图层转到同一 CRS。转完先各自total_bounds看一下范围有没有交集再执行裁剪。4.2 现象面积统计结果明显偏大或偏小原因在地理坐标系下直接调用了面积字段或者投影带选择错误。经纬度下geometry.area返回的是平方度数值看着像那么回事实际没有意义。解决确认当前 CRS 是投影坐标系且中央经线覆盖研究区。跨带时改用等面积投影或者分带计算后汇总。4.3 现象分区统计报错「栅格与矢量范围不重叠」原因栅格和矢量的坐标系虽然名字一样但一个是地理坐标、一个是投影坐标或者栅格的原点、分辨率导致边界对不上。解决用gdalinfo或 QGIS 图层属性确认栅格 CRS和矢量统一。必要时先用矢量范围裁剪栅格再跑分区统计减少无效计算。4.4 现象属性表中文名称乱码原因Shapefile 的 DBF 默认编码和实际写入编码不一致常见于从其他格式转换过来。解决读取时显式指定encodingutf-8或encodinggbk试一次如果已经乱码用gpd.read_file读进来后重新写一份 GeoPackage 或 FileGDB这两种格式对中文支持更稳。4.5 现象同一个三级流域编码出现多条记录原因几何被河流或行政区切碎或者数据本身是多部件几何被拆开存储。解决按编码做dissolve合并再重新计算面积。合并前确认这些碎片的属性一致避免把不同二级流域的同名编码误合。merged clipped.dissolve(byL3_CODE, aggfuncfirst) merged[area_km2] merged.to_crs(EPSG:4547).geometry.area / 1e6dissolve按编码合并几何aggfuncfirst保留第一条属性。合并后必须重新投影算面积因为几何变了。5. 进阶把三级流域和监测点位做空间关联的稳定套路5.1 点位落在哪个流域别只用「相交」把水质监测点、雨量站、排污口落到三级流域上最直接的是sjoin。但实际数据里点位可能正好落在流域边界上或者因为坐标偏移落在外面。我一般会做两步先精确sjoin再对没匹配上的点做最近邻兜底。import geopandas as gpd points gpd.read_file(stations.shp).to_crs(basin.crs) joined gpd.sjoin(points, basin, howleft, predicatewithin) # 没匹配上的用最近流域补 missing joined[joined[L3_CODE].isna()].copy() if len(missing) 0: nearest gpd.sjoin_nearest(missing, basin, howleft) joined.loc[missing.index, L3_CODE] nearest[L3_CODE].valuespredicatewithin比intersects更严格避免边界点被重复匹配。sjoin_nearest是兜底手段但要注意它可能把点归到隔着一条河的流域所以只对少量缺失点用并且人工抽查几条。5.2 用编码前缀做层级聚合前面提过编码前缀能直接聚合。假设三级编码是 8 位前 2 位一级、前 4 位二级basin[L1_CODE] basin[L3_CODE].str[:2] basin[L2_CODE] basin[L3_CODE].str[:4] l1_stats basin.dissolve(byL1_CODE, aggfuncsum)[[area_km2]]这样你不用额外找一级、二级的边界文件直接从三级聚合上去。前提是编码规则确实按层级前缀设计——拿到数据先验证几个已知流域的编码是否符合这个规律别想当然。5.3 一个我常做的验证用已知断面反查汇水区数据准不准拿一个你熟悉的断面验证最直接。比如你知道某水文站控制面积是 3000 平方公里就在三级流域里按编码或空间位置找到对应单元把面积加起来看是否接近。差太多要么是流域划分粒度和你预期不一致要么是投影或几何有问题。验证项预期常见偏差原因单流域面积与公开资料接近投影带选错聚合面积等于各分项之和几何重叠或重复点位归属与人工判断一致边界点匹配规则编码层级前缀符合规则数据版本差异从那以后我每次拿到新的流域数据都强制走一遍「投影确认 → 几何修复 → 编码查重 → 已知断面验证」这四步少一步后面就可能返工。希望帮到你。本文还有配套的精品资源点击获取
返回列表