ARTICLE DETAIL

资讯详情

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

云南河流水系shp数据实战:坐标系、裁剪与河网密度统计

云南河流水系shp数据实战:坐标系、裁剪与河网密度统计 简介这份2024年云南省河流水系矢量图层shp数据面向从事GIS分析、地图制图、水文研究及空间数据可视化的技术人员与学习者可用于省级水系分布展示、流域分析、底图制作等场景。资源包共11个文件以shp、shx、dbf、prj、cpg等标准矢量格式为主分别承载几何图形、索引、属性表、坐标系与字符编码信息另附一个py脚本压缩包整体约16.15MB。数据涵盖水系线与水系面两类图层记录达几千上万条细节颗粒度较高坐标系为WGS1984便于直接导入ArcGIS、QGIS等平台使用。目前已有235人学习下载。对于需要快速获取云南全省水系基础数据的用户而言可直接省去繁琐的采集与整理环节用于专题制图、空间叠加与水文连通性分析也可作为教学演示与项目底图素材兼顾完整性与实用性。1. 云南水系 shp 拿到手之后先搞清楚它能干什么、不能干什么做水文分析、流域规划、GIS 底图配图的人大概率都遇到过同一个尴尬底图上的河流要么是栅格图片糊成一片要么是某地图 API 截下来的瓦片放大就散。真正能拿来做缓冲区分析、流域裁剪、汇流计算的必须是带属性表的矢量线图层。2024 云南省河流水系矢量图层 shp 数据解决的就是这个从「看得见」到「算得动」的断层。它把全省河流水系按线要素组织成标准 shapefile能在 ArcGIS、QGIS、PostGIS 里直接加载、查询、裁剪、叠加。适合做流域边界提取、河网密度统计、水利选址、地图出版底图的人不适合只想找一张好看河流图片贴 PPT 的人因为 shp 的价值在属性字段和拓扑不在渲染效果。2. 拆开这份 shp字段结构、坐标系与数据组织方式2.1 shapefile 三件套到底装了什么shapefile 不是单个文件而是一组同名文件的集合。拿到压缩包解压后你至少会看到.shp、.shx、.dbf三个缺一个都打不开。.shp存几何形状.shx是索引.dbf是属性表类似数据库里的字段列。如果还带了.prj那说明坐标系定义是完整的这个文件千万别删——很多人把 shp 发给同事对方打开发现位置飘到国外去了十有八九就是.prj丢了或者坐标系对不上。常见做法是解压后先别急着拖进软件先在文件夹里确认这几个文件是否同名同目录。QGIS 对缺失.prj的容错比 ArcGIS 好一些会提示你手动指定坐标系ArcGIS 则可能直接按未知坐标系处理导致和别的图层叠不上。提示.cpg文件控制.dbf的字符编码。如果打开后中文属性显示乱码先看有没有.cpg没有就手动指定 UTF-8 或 GBK 试。2.2 坐标系判断地理坐标还是投影坐标河流水系数据最常见的两种坐标系一种是地理坐标系如 GCS_WGS_1984单位是度一种是投影坐标系如 CGCS2000 3 度带单位是米。判断方法很直接打开属性表看几何或者看图层坐标范围。如果 X 坐标在 97 到 106 之间、Y 在 21 到 29 之间那是经纬度如果 X 是六位数、Y 是七位数那是投影坐标。为什么这件事重要因为你要做长度统计、缓冲区分析时地理坐标系下的「米」是不准的度不能直接当米用。正确做法是先投影。云南跨了多个 3 度带如果做全省尺度分析建议统一用 CGCS2000 或 WGS84 的 Albers 等积投影而不是某个单带投影否则东西两端变形会很明显。# 用 GDAL 查看 shp 的坐标系和范围不用打开桌面软件 ogrinfo -al -so yunnan_rivers.shp # 输出里重点看这几行 # Geometry: Line String # Feature Count: xxxx # Extent: (97.xx, 21.xx) - (106.xx, 29.xx) # Layer SRS WKT: GEOGCS[GCS_WGS_1984, ...]ogrinfo -al -so里的-so表示只输出摘要不列要素速度快。Extent帮你判断坐标单位Layer SRS WKT帮你确认坐标系名称。如果这里显示的是GEOGCS而你要做长度量算下一步就得投影。2.3 属性字段河流名称、等级、编码怎么用一份合格的河流水系 shp属性表里通常会有河流名称、河流等级一级、二级……、河流编码这几类字段。字段名可能是中文也可能是拼音缩写比如NAME、GRADE、CODE。不同来源的数据字段命名不统一这是常态别指望开箱即用。我一般会先做一次字段体检用ogrinfo看字段列表或者用 Python 的fiona读 schema。确认哪些字段能用来筛选。比如你只想要干流就按等级字段过滤你要做河网密度就得保证线要素没有重复、没有断头线。import fiona with fiona.open(yunnan_rivers.shp, encodingutf-8) as src: print(坐标系:, src.crs) print(几何类型:, src.schema[geometry]) print(字段列表:) for field, dtype in src.schema[properties].items(): print(f {field}: {dtype}) print(要素总数:, len(src))这段代码用fiona读取 shp 的元信息不加载全部几何内存占用低。src.crs返回坐标系src.schema返回几何类型和字段定义。跑完你就能知道这份数据有没有等级字段、名称字段是中文还是英文。如果字段名是NAME但值是乱码检查encoding参数改成gbk再试。3. 把 shp 用起来加载、裁剪、筛选与格式转换3.1 在 QGIS 和 ArcGIS 里正确加载QGIS 加载 shp 最省事直接把.shp拖进窗口或者图层菜单里选「添加矢量图层」。如果坐标系没定义QGIS 会弹窗让你选这时候别随便点一个去查数据说明或者用ogrinfo确认。ArcGIS 里用「添加数据」按钮注意不要用「添加底图」那是两回事。加载后第一件事不是配符号是检查位置对不对。叠一个已知正确的行政区划或者影像底图看河流是不是落在云南范围内。如果飘了就是坐标系问题不是数据坏了。注意ArcGIS 对中文路径和中文文件名有时会出问题养成用英文路径的习惯能省很多玄学故障。3.2 按属性筛选目标河流全省水系数据动辄几万条线要素全量渲染会卡。实际项目里通常只需要特定等级或特定流域的河流。按属性筛选是最快的方式。import geopandas as gpd gdf gpd.read_file(yunnan_rivers.shp, encodingutf-8) # 假设字段名是 GRADE筛选一级和二级河流 main_rivers gdf[gdf[GRADE].isin([一级, 二级])] # 按名称模糊筛选比如所有含“金沙江”的 jinsha gdf[gdf[NAME].str.contains(金沙江, naFalse)] main_rivers.to_file(yunnan_main_rivers.shp, encodingutf-8) print(筛选后要素数:, len(main_rivers))gpd.read_file直接返回 GeoDataFrame可以像操作 pandas 一样筛选。isin用于多值匹配str.contains用于模糊匹配naFalse避免空值报错。导出时指定encodingutf-8防止中文属性丢失。这一步的坑在于字段值可能有空格或全半角差异筛选前先gdf[GRADE].unique()看一眼实际值。3.3 用行政区边界裁剪水系如果你只关心某个市或某个流域的河流用边界裁剪比按属性筛选更彻底。常见做法是用geopandas的clip或者overlay。import geopandas as gpd rivers gpd.read_file(yunnan_rivers.shp, encodingutf-8) boundary gpd.read_file(study_area.shp, encodingutf-8) # 统一坐标系后再裁剪否则结果为空或报错 if rivers.crs ! boundary.crs: boundary boundary.to_crs(rivers.crs) clipped gpd.clip(rivers, boundary) clipped.to_file(rivers_clipped.shp, encodingutf-8) print(裁剪后要素数:, len(clipped))to_crs做坐标系转换gpd.clip按边界几何裁剪。关键点是裁剪前必须统一坐标系这是新手最容易翻车的地方——两个图层坐标系不一致时clip可能返回空结果而不报错。裁剪后要素数应该小于等于原始数如果等于原始数说明边界没覆盖到或者坐标系没对上。3.4 shp 转 GeoJSON、WKT 与 3D Tiles 的取舍项目里经常要把 shp 转成别的格式。转 GeoJSON 用于 Web 地图转 WKT 用于数据库存储转 3D Tiles 用于三维场景。工具选择上GDAL 的ogr2ogr是万能选手。# shp 转 GeoJSON指定坐标系和编码 ogr2ogr -f GeoJSON -t_srs EPSG:4326 rivers.geojson yunnan_rivers.shp -lco ENCODINGUTF-8 # shp 属性导出为 txt只导属性表不含几何 ogr2ogr -f CSV rivers_attr.csv yunnan_rivers.shp -lco GEOMETRYAS_WKT-f指定输出格式-t_srs指定目标坐标系-lco是图层创建选项。转 GeoJSON 时如果中文乱码加ENCODINGUTF-8。导出 CSV 时GEOMETRYAS_WKT会把几何写成 WKT 字段方便导入数据库。转 3D Tiles 不是ogr2ogr直接能做的需要先转成带高度的矢量再用专门工具切片这一步对坐标系和高度字段要求更严建议单独验证。4. 避坑与排查坐标系、编码、拓扑这几关最容易翻车4.1 现象图层叠加后位置偏移几百米原因两个图层坐标系不一致或者其中一个缺少.prj被软件按默认坐标系处理。解决用ogrinfo确认两者坐标系统一用to_crs转换后再叠加。不要靠肉眼拖动对齐那是自欺欺人。4.2 现象属性表中文显示为问号或乱码原因.dbf的编码和软件读取编码不匹配常见于 GBK 数据被按 UTF-8 读。解决检查有无.cpg文件没有就手动创建内容写UTF-8或GBK。QGIS 里可以在图层属性中改编码重新加载。4.3 现象裁剪结果为空但边界明明有重叠原因坐标系没统一或者边界几何本身有问题自相交、空几何。解决先to_crs统一坐标系再用boundary.is_valid检查几何有效性无效的用buffer(0)修复。4.4 现象河流线要素有断头、重复、悬挂原因数据采集时分段录入或者合并多个来源时没做拓扑检查。解决用 QGIS 的拓扑检查器或者geopandas做重复几何检测断头线根据项目精度要求决定是否合并。做河网密度统计前必须处理否则结果偏大。4.5 现象导出 GeoJSON 后文件巨大网页加载卡死原因shp 几何精度过高顶点密集。解决导出前做简化ogr2ogr加-simplify参数或者用geopandas的simplify方法。简化容差根据出图比例尺定别一刀切。5. 进阶技巧用 Python 批量做河网密度统计与结果验证河网密度是水系数据最常用的派生指标之一单位面积内的河流长度。手工算不现实用geopandas配合渔网分割可以批量出结果。思路是先按研究区生成渔网再把河流按渔网裁剪统计每个网格内的河流总长度除以网格面积。import geopandas as gpd import numpy as np rivers gpd.read_file(yunnan_rivers.shp, encodingutf-8) study gpd.read_file(study_area.shp, encodingutf-8) # 统一投影坐标系单位用米 rivers rivers.to_crs(epsg4526) study study.to_crs(epsg4526) # 生成渔网这里用 10km x 10km from shapely.geometry import box minx, miny, maxx, maxy study.total_bounds cell 10000 cols list(np.arange(minx, maxx, cell)) rows list(np.arange(miny, maxy, cell)) cells [box(x, y, x cell, y cell) for x in cols for y in rows] grid gpd.GeoDataFrame({geometry: cells}, crsstudy.crs) # 用研究区裁剪渔网 grid gpd.clip(grid, study) # 河流与渔网叠加计算每个网格内河流长度 intersect gpd.overlay(rivers, grid, howintersection) intersect[length] intersect.geometry.length density intersect.groupby(intersect.index_right)[length].sum().reset_index() density grid.reset_index().merge(density, left_onindex, right_onindex_right, howleft) density[length] density[length].fillna(0) density[area] density.geometry.area density[density] density[length] / density[area] density.to_file(river_density.shp, encodingutf-8) print(density[[density]].describe())这段代码的关键参数是cell控制渔网大小10km 适合市域尺度县域可以缩到 1km 或 2km。epsg4526是 CGCS2000 的 3 度带投影单位是米保证长度和面积计算正确。overlay做相交groupby按网格汇总长度。最后用describe()看密度分布如果最大值异常大回去检查是否有重复线或者网格面积计算错误。验证方法挑一个网格手工在 QGIS 里量一下河流长度和脚本结果对比。误差在 5% 以内说明流程没问题。我一般还会把密度结果按分位数分级渲染看空间分布是否符合地理常识——河流密集区应该和降水、地形吻合如果密度高值出现在干旱坝区那大概率是数据或投影出了问题。从那以后我每次拿到新的水系 shp都强制走一遍「查坐标系 → 验编码 → 查拓扑 → 试裁剪」这四步不再直接拖进软件就开工。希望帮到你。本文还有配套的精品资源点击获取
返回列表