简介长江流域岷江、沱江水系流域地形图矢量与栅格数据包面向需要在ArcGIS中开展区域制图、水文分析或科研底图配置的研究人员和GIS初学者。压缩包共63个文件、约42.74MB其中shp配合dbf、prj、shx、sbn/sbx构成河流、湖区等可编辑矢量图层adf、hdr等栅格文件记录DEM地形与山体阴影数据mxd工程文件让GIS新手也能快速关联图层并一键出图包内还预导出jpeg、PDF、EPS三种常见格式的地形图不熟悉GIS的用户也可直接用于打印、汇报或插图。已有1353人学习下载。整体省去了从公开数据中查找、裁剪、配准和符号化的流程既能满足GIS操作练习又能用于课程作业、论文插图或项目汇报的底图需求数据经网络收集和二次加工适合学习科研或个人项目前期参考实际使用前应按需核验精度与时效。1. 岷江沱江水系shp数据拉进ArcGIS之前必须先处理的三件事做防洪评估或者岸线规划时大家最想要的就是一张长江流域岷江沱江水系的流域地形图shp格式矢量文件。可这类文件真正拿到手多数人第一步就卡在ArcGIS里要么双击之后报“无法添加数据”要么要素全部挤在经纬度零点附近要么属性表里流域名称、编码全是空的。问题很少出在ArcGIS本身而是出在shp格式的文件结构、坐标系定义和属性字段这三件基础事上。这篇内容就是把“拿到一份候选shp”到“能在ArcGIS里正常出图、算面积、按岷江与沱江边界做提取”的完整过程拆开讲适合做防洪排涝规划、水资源评价、流域水环境管理以及准备论文底图的工程师和在校学生。2. 认识shp文件本身主文件、伴随文件与坐标系2.1 shp不是“一个文件”而是“一组文件”很多同事在拷贝数据时只复制了扩展名为.shp的那一个文件拿到另一台机器上一打开属性表是空的图形也时有时无于是到处问“这数据是不是坏了”。实际上shapefile从设计之初就不是单个文件而是一个文件家族至少包含几何、索引和属性三套伴随文件。判断一份shp能不能用第一步不是打开ArcGIS而是看目录里的文件是否齐全。扩展名作用缺失时的典型表现.shp要素几何坐标的主文件无法打开提示“Shapefile无效”.shx几何位置索引文件读取极慢或直接失败.dbf属性表流域名称、编码、面积都在这里要素只剩形状属性表为空.prj坐标系描述文件以WKT文本保存坐标系未知显示位置错乱.cpg字符编码声明中文属性字段大概率乱码.sbn / .sbx空间索引文件影响查询性能不影响基本打开其中.shp、.shx、.dbf三者必须成套.prj决定坐标系是最影响使用体验的文件。很多人拿到数据后直接把整个文件夹压缩发给别人看似省事一旦中间有人只拖出.shp文件后续麻烦就开始了。我现在的习惯是无论从哪个渠道拿到数据先用命令行看一眼目录下到底有哪些伴随文件。# 查看目标目录下全部伴随文件是否齐全 ls -la /path/to/minjiang_tuojiang/在Windows上对应使用dir命令。看到.shp与.shx、.dbf同时存在才说明几何与属性是完整的如果只有.shp再考虑联系数据提供方补全。更重要的是需要检查是否存在.prj没有.prj的文件后面一定会出坐标系问题。这里有一个血泪经验给第三方转数据时尽量用ArcGIS的“要素类导出至Shapefile”功能让软件自动把伴随文件生成完整而不是手动去文件夹里挑几个文件复制。2.2 坐标系才是“漂移”现象的源头把shp拉进ArcGIS后要素出现在赤道附近或者图形的经纬度数值只有0.几这基本都不是数据损坏而是坐标系缺失或者定义错误。ArcGIS里有两套坐标系概念要分清地理坐标系用经纬度表达位置单位是度投影坐标系把地球表面展开到平面上单位是米。流域shp通常生产时使用国家地理坐标系例如CGCS2000或WGS84再经高斯-克吕格投影到二维平面。问题是很多共享数据在导出时丢了.prj文件ArcGIS没有办法判断要素坐标的单位默认按未知坐标系处理自然就显示在错误位置。判断坐标系的第一步是读.prj文件里的WKT字符串。它虽然看着复杂但关键段落并不多。# 读取 .prj 文件中的 WKT 文本查看坐标系描述 with open(minjiang_tuojiang.prj, r, encodingutf-8, errorsreplace) as fp: wkt fp.read() print(wkt[:600])代码的逻辑很简单就是按文本方式读取投影描述。阅读时优先看三处GEOGCS后面是地理坐标系名称例如“China Geodetic Coordinate System 2000”代表CGCS2000PROJCS代表投影坐标系PARAMETER[central_meridian,105]表示中央经线为105度。如果没有.prj文件ArcGIS就会把坐标系标记为“Unknown”这就是漂移的直接原因。遇到这种情况不要凭感觉在图层属性里乱选坐标系而应该先向数据提供方确认原始坐标基准如果确实问不到就借助数据范围反推这部分在第五章展开。2.3 流域shp的属性表里到底存了些什么识别清楚文件结构与坐标系之后下一步是打开属性表看字段。一份规范的流域shp属性表里通常包含流域名称、流域编码、级别、计算面积、所属干流等字段。对于岷江沱江水系比较理想的情况是“名称”字段里有“岷江水系”“沱江水系”这样的标识或者“编码”字段带独立的水系编码前缀。有些数据集还会把流域边界拆成多个级别比如一级流域、二级流域、三级子流域这种情况下一个shp里会同时存在几百上千个小面片名称字段经常重复。特别注意“水系”和“流域”是两个概念水系shp一般是线状河网表达岷江干支流河道流域shp是面状区域表达汇水范围。标题里的“流域地形图”通常二者都有加载之后内容列表里至少出现一个面图层和一个线图层。在开始做任何提取操作前我建议先打开属性表把字段列表截图或记录确认名称字段和编码字段的真实字段名。不同渠道的数据字段命名风格差异很大有的是NAME有的是DLBM还有的干脆叫F1、F2。这一步不做好后面筛选岷江和沱江时就只能靠肉眼一个个找既慢又容易漏。3. 拿到一份能用的流域shp数据源选型与一条命令体检3.1 数据源选型不要看到“流域”两个字就下手标题里点名了“长江流域岷江沱江水系”这类数据在公开渠道并不稀缺常见来源大致有四类一是国家级地理信息服务平台发布的全国1:100万和1:25万基础地理数据其中包含水系与流域边界二是水利行业开放的水文基础数据共享站点更侧重流域分区编码与河流关系三是高校或科研单位整理发布的流域数据集通常按流域边界做好了属性整理四是商业数据服务商按需求定制。每一类数据的特点差异很大直接决定你后续在ArcGIS里要花多少时间收拾它。来源类型坐标系情况属性完整度适合场景地理信息公共服务数据多为CGCS2000地理坐标属性较完整全国范围制图水利行业共享数据多为CGCS2000或投影坐标字段齐全有编码体系水文分析与防洪高校科研共享数据水平参差常有坐标系缺失字段命名风格不统一论文与科研速用商业定制数据按需求定义完整且带说明书生产项目交付选型时建议只看四件事坐标系是否有定义、属性字段是否完整、数据更新年份、原始比例尺。很多网上流传的长江流域shp已经是多次转手的版本字段被截断过投影参数被改过甚至面积字段和实际几何面积完全对不上。如果数据附带说明文档一定先读说明特别是其中关于坐标系和字段字典的部分比数据本身更值钱。我一般会下载两到三份不同来源的数据做比对避免单份数据的问题直接影响后续分析结论。3.2 用Python快速给shp做体检一条命令看清家底不管数据是哪个渠道来的我拿到手的第一动作都是先用Python把整个shp扫描一遍而不是着急打开ArcGIS。这样能在几十秒内确定坐标系、要素数量、几何类型、字段列表和空间范围避免把有明显问题的大文件拖进工程后发现没法用。下面的脚本是最小体检版本只需要安装geopandas和pyogrio两个库。# -*- coding: utf-8 -*- # 环境准备: pip install geopandas pyogrio import geopandas as gpd shp_path minjiang_tuojiang.shp gdf gpd.read_file(shp_path, enginepyogrio) print(空间参考:, gdf.crs) print(要素数量:, len(gdf)) print(几何类型:, gdf.geom_type.unique()) print(字段列表:, list(gdf.columns)) print(图层范围:, gdf.total_bounds) print(空几何数量:, gdf.geometry.isna().sum())这段代码的逻辑是用pyogrio引擎读取shp打印六个关键信息。参数说明如下gdf.crs直接显示坐标系对应的EPSG编号total_bounds返回一个包含最小X、最小Y、最大X、最大Y的数组其单位取决于数据本身的坐标系geom_type.unique()告诉你这个文件里是点、线还是面。如果打印出来的范围是类似[97.0, 28.0, 106.0, 34.0]这样的经纬度范围说明地理坐标如果是[3400000, 3100000, 3600000, 3300000]这样的大整数范围说明是投影坐标。这一步能直接发现坐标系与数值范围是否匹配。执行过程中如果遇到“Unable to open”之类的错误先把路径复制到纯英文目录下再跑Windows系统中路径里的中文或特殊符号经常导致读取失败。这个细节看着小但在实际项目中卡住不少新手。3.3 判断这份数据能不能用先看3个硬指标体检脚本跑完之后数据能不能进ArcGIS做正式分析我只看三个硬指标。第一坐标系是否有定义且范围合理打印出的坐标系不能是空值同时范围数值要与坐标系统一。如果是CGCS2000地理坐标系范围应该在经度73到135、纬度3到54之间如果经纬度范围出现零点附近的值基本可以判定prj丢失。第二几何有效gdf.geometry.isna().sum()的值必须为0空几何在ArcGIS里不会直接报错但做相交、裁剪时会被当作无效要素处理。第三关键字段完整打开字段列表后确认是否存在流域名称和流域编码字段并抽样检查这两个字段的空值比例。只要这三个条件不满足再漂亮的数据也不要直接用于项目否则后面每做一步操作都要怀疑结果是数据问题还是参数问题。4. ArcGIS里的完整操作流程从加载、投影到提取岷江沱江水系4.1 在ArcGIS中加载shp并统一坐标系数据通过体检后就可以正式进入ArcGIS。先在建好的工程里创建文件夹连接把shp所在的目录挂进去然后从目录面板把.shp直接拖到地图视图中。加载完成后右键图层打开属性在“源”选项卡里确认ArcGIS识别出的空间参考。如果这里显示“Unknown”就要回头补定义投影操。注意定义投影和投影变换是两个完全不同的工具前者只是告诉ArcGIS“这份数据实际是什么坐标系”后者才是真正把坐标值换算到另一个坐标系。两个工具都在数据管理工具箱的“投影与变换”工具集下。如果是已有.prj但坐标系不符合当前工程需要就需要执行投影变换。对于岷江沱江流域范围我通常会把数据投影到中央经线105度的CGCS2000高斯-克吕格3度分带坐标系这样可以比较准确地计算面积。工具参数设置可以参考下表。工具参数推荐取值说明输入数据集原始shp保留原文件不要在源文件上直接覆盖输出数据集新命名shp建议加“_105”之类后缀输出坐标系CGCS2000 / 3-degree Gauss-Kruger CM 105E覆盖岷江沱江范围面积变形最小地理变换按源数据基准选择源为WGS84时需指定转换参数如果数据本身已经是CGCS2000地理坐标系那么在ArcGIS里做投影时不需要填地理变换参数如果源坐标系是WGS84理论上需要一个地理变换但在实际制图项目中很多制图单位为了省事直接忽略这一步。我的建议是普通出图可以忽略涉及面积计算和坐标精度要求较高的分析不建议忽略。用ArcPy脚本可以更精准地控制参数。import arcpy in_features rC:\data\minjiang_tuojiang.shp out_features rC:\data\minjiang_tuojiang_105.shp # 定义输出坐标系: CGCS2000 高斯-克吕格投影, 3度分带, 中央经线105°E out_coord_system arcpy.SpatialReference(CGCS2000 / 3-degree Gauss-Kruger CM 105E) # 源数据如果为CGCS2000地理坐标系, 此处不需要地理变换 arcpy.Project_management(in_features, out_features, out_coord_system) print(投影完成:, arcpy.Exists(out_features))这个脚本里最关键的是arcpy.SpatialReference(CGCS2000 / 3-degree Gauss-Kruger CM 105E)坐标系名称必须与ArcGIS内置名称完全一致。如果不确定名称可以在投影工具的坐标系选择界面里搜索“CGCS2000 3 Degree”来确认。Project_management的参数顺序是输入、输出、坐标系输出要素路径必须用完整路径否则默认写到ArcGIS默认地理数据库而不是你要的文件夹。4.2 从长江流域全量数据里提取岷江沱江水系子流域很多共享数据是整个长江流域的shp要拿到岷江沱江水系就必须做要素提取。最直观的操作是打开属性表使用“按属性选择”工具在SQL语句里把两个水系的名称写进去。常见写法是NAME IN (岷江水系, 沱江水系)。不过我更建议先看字段里到底有哪些值再决定筛选条件因为有些数据集的名称字段只写干流名支流区域名称是其他值。实际操作步骤是在属性表里点击“按属性选择”选择名称字段点击“获取唯一值”查看所有可能取值然后组合出正确的SQL语句确认查询结果正确后右键原始数据图层使用“数据”菜单下的“导出数据”将选中要素另存为shp。这个操作不会修改源数据算是安全的做法。用ArcPy完成同一件事可控性更强。import arcpy in_fc rC:\data\changjiang_basins.shp # 长江流域全量面图层 out_fc rC:\data\minjiang_tuojiang_basins.shp # 先输出字段列表确认字段名后再执行筛选 fields [f.name for f in arcpy.ListFields(in_fc)] print(可用字段:, fields) # 按名称字段筛选岷江水系与沱江水系 where_clause NAME IN (岷江水系, 沱江水系) arcpy.Select_analysis(in_fc, out_fc, where_clause) print(提取完成:, arcpy.Exists(out_fc))这里Select_analysis是数据管理工具箱里的经典工具三个参数分别是输入要素、输出要素和SQL条件。需要注意的是dbf属性表对SQL语句的支持有限字段名如果是中文且带有空格必须在SQL里用双引号括起来。在ArcGIS的查询构建器里会自动处理引号问题但直接写在脚本里很容易踩坑。建议先执行ListFields把字段名打印出来再构造查询条件。还有一个常见问题字段值里包含全角空格或前后空格导致IN条件匹配不到这时可以先执行字段计算器去掉字符串两端空格。4.3 叠加DEM做水文分析反向检查shp的精度提取出岷江沱江水系子流域后建议做一次地形套合检查方法是把shp叠加到DEM上。加载DEM数据后给它设置一个带透明度的山体阴影渲染再把流域边界shp叠加在上面立刻可以看出流域边界是否沿着山脊线走。如果边界明显切过山谷或河流说明这份shp的流域边界不是严格的地形分水岭可能来自小比例尺基础地理数据或经过人为简化。更进一步可以直接用ArcGIS的Spatial Analyst水文分析工具从DEM上重新提取一遍流域边界和已有shp对比。常见流程是填洼、计算流向、计算累积流量、按阈值提取河网、生成流域栅格、转为矢量。这套流程里最影响结果的参数是累积流量阈值它决定了提取的河网密度。以30米分辨率DEM为例投影后单个栅格面积是900平方米如果设定阈值1000个栅格等效汇水面积约0.9平方公里得到的河网密度适中阈值越小河网越密但杂支越多。对比shp里的实测河网与自动提取河网如果主流位置基本重合说明地形数据与shp数据来源差不多如果明显偏移则更应以DEM为准重新划分流域。这一套流程做完才能对要使用的shp数据真正建立起信任。5. 使用岷江沱江shp时绕不开的5个坑现象、原因与解决5.1 缺.prj导致所有要素挤到赤道附近现象把shp拖进ArcGIS比例尺自动缩到全球范围要素全部堆在非洲西海岸或赤道附近图层缩放不到正常范围。原因本质上就是缺少.prj文件ArcGIS不知道这些坐标是经纬度还是投影值随意把坐标当作十进制经纬度显示自然渲染到海上。还有一种情况是.prj存在但内容不正确常见于有人在别的工程里乱选坐标系后另存这类数据在加载时不会报错但位置偏移非常隐蔽。解决如果是单纯缺失.prj先问数据源确认坐标系然后把数据范围打印出来辅助判断。假设要素范围是经度98到107度纬度28到34度基本可以确定是地理坐标使用“定义投影”工具选择CGCS2000地理坐标系即可。如果坐标值是非常大的整数范围那多半是投影坐标需要在附近找对应的中央经线。这里要特别提醒不要在无法确认的情况下反复尝试不同的投影坐标系去“碰运气”每一次错误定义都会让数据状态更混乱最稳妥的做法是找原始数据下载页或说明文档里的坐标系描述。5.2 属性表中文乱码、汉字变成“锟斤拷”一类符号现象ArcGIS中打开属性表“岷江水系”显示为乱码或者在ArcGIS里看正常导出给别人后乱码。原因dbf属性表的字符编码由.cpg文件声明缺少这个文件时软件会按系统本地化设置猜测编码。国内大部分水文部门的数据当初是以GBK或GB2312编码生成的而新版ArcGIS环境默认读取为UTF-8导致中文解码错位。这类问题很容易被误判为字体问题或数据损坏。解决最直接的办法是用Python按指定编码重新读取再按UTF-8写一份新shp。import geopandas as gpd # 按GBK解码读取旧数据, 再输出为UTF-8编码的新数据 gdf gpd.read_file(old_gbk.shp, encodinggbk) gdf.to_file(new_utf8.shp, encodingutf-8)这段代码的核心在两个参数read_file的encoding参数指定dbf属性表解码方式to_file的encoding参数指定写入编码。如果GBK解码之后还是乱码可以依次尝试gb18030和utf-8两种编码。修正编码之后重新在ArcGIS中打开属性表中文就能正常显示。另外提醒一点处理这类文件要在副本上进行不要在原始数据上原地覆盖。5.3 流域边界与最新影像或地形对不上现象把shp边界叠加到影像底图上发现有部分边界明显穿过山脊下方或者斜切河谷与肉眼判断的分水岭不符。原因shp的流域边界通常是根据某一时期的地形图或遥感影像勾绘的比例尺决定了它的精度。如果数据是基于1:100万小比例尺生产反映到局部山区时误差可能达到数百米。另一个常见原因是流域范围内有大型水库和引水工程人工改变水流方向后原有自然分水岭边界不再适用。解决对精度要求高的项目我一般直接让shp边界退到辅助参考位置用DEM重新提取的分水岭作为分析边界shp只保留河流名称和编码属性。具体做法是把DEM水文分析生成的分水岭面要素与原有shp做空间连接把名称字段属性复制到新边界上。如果只是出示意图纸可以在图面注记里写清楚数据来源与年份避免后续使用者误读。5.4 按名称筛选后夹杂大量细碎面片现象通过SQL查询把“岷江水系”和“沱江水系”筛选出来后结果里有几百个只有几平方公里甚至更小的面片图纸上密密麻麻无法整体出图。原因许多长江流域数据集在生产时按特定层级进行了细分把大流域拆到一个个小集水区。名称字段可能都带“岷江水系”但面片粒度极细。直接按名称筛选会把该水系下所有等级的面一起选出来碎面也就跟着进来了。解决先在属性表里查看“级别”或“等级”字段如果有类似一级、二级、三级的值筛选时加上级别条件只保留目标级别。如果没有级别字段用面积字段过滤在查询条件里加上AREA 100这样的限制单位是已投影要素的平方千米。对于只想保留一个大面边界的场景可以在筛选后执行“融合”工具按流域名称字段融合所有小面片。融合之后再做数据导出图面就干净多了。import arcpy # 过滤面积小于 100 平方公里的小碎面后再融合 where_area SHAPE_AREA 100000000 arcpy.MakeFeatureLayer_management(out_fc, basin_layer, where_area) arcpy.Dissolve_management(basin_layer, rC:\data\minjiang_tuojiang_dissolve.shp, NAME)Dissolve_management的第三个参数是融合字段这里用名称字段结果是一个属性被合并成一行的大面要素。参数SHAPE_AREA只存在部分要素类中如果字段里没有可以先用“添加几何属性”工具生成面积字段再写条件。5.5 几何错误导致裁剪、相交工具报错或速度极慢现象用原始shp执行“相交”或“裁剪”工具时经常弹“几何无效”错误或者同一份数据别人处理很快自己这边却跑几分钟不结束。原因shp数据在编辑过程中未做拓扑检查导致要素存在自相交、重复节点、空几何等问题。ArcGIS的很多分析工具在遇到自相交几何时会直接终止运算或者按跳过无效几何的方式静默处理从而产生残缺结果。解决先用“检查几何”工具生成一份错误报告再用“修复几何”工具批量修复。如果手上没有ArcGIS许可环境可以用Python做一次快速兜底。import geopandas as gpd gdf gpd.read_file(input_with_errors.shp) print(修复前有效要素占比:, round(gdf.geometry.is_valid.mean(), 3)) # buffer(0) 是常见的自相交修复思路 gdf[geometry] gdf.geometry.buffer(0) gdf.to_file(input_repaired.shp, encodingutf-8)这段代码的关键是buffer(0)对几何执行零距离缓冲会让软件重新计算几何拓扑自动消除细小的自相交和重复点。但它不是万能药对于复杂的线面交叉可能需要调整修复策略。修复完成后再用“检查几何”工具复检一遍确认有效要素占比接近100%再进入分析流程。这也是我反复强调要先备份原始文件的原因缓冲区修复在个别情况下会改变边界细节虽然多数场景无感知但如果下游要严格对接坐标值最好直接比对修复前后的要素坐标变化量。6. 进阶用ArcPy脚本批量检查整个目录的shp数据质量当把整套流程跑通之后我强烈建议把所有检查动作沉淀成脚本因为流域类数据往往不是单份文件而是一个目录下几十个shp逐个打开属性表查看效率太低。下面这个脚本可以遍历指定文件夹把每个shp的坐标系、要素类型、PRJ是否存在等信息汇总成csv表格检查过程一眼看完。import arcpy import os import csv folder rD:\watershed_data results [] # 递归遍历目录下所有要素类 for root, _, files in arcpy.da.Walk(folder, datatypeFeatureClass): for f in files: if not f.lower().endswith(.shp): continue path os.path.join(root, f) desc arcpy.Describe(path) sr desc.spatialReference results.append([ f, desc.shapeType, sr.name if sr.name else 未定义, sr.factoryCode if sr.factoryCode else ]) # 输出带 BOM 的 UTF-8 CSV, 方便 Excel 直接打开 with open(shp_summary.csv, w, newline, encodingutf-8-sig) as fp: writer csv.writer(fp) writer.writerow([文件名, 要素类型, 坐标系名称, EPSG/工厂代码]) writer.writerows(results) print(已输出 shp_summary.csv, 共检查, len(results), 个shp)脚本的逻辑是使用arcpy.da.Walk遍历目录下所有要素类用Describe获取每个shp的描述属性最后写入csv。这里datatypeFeatureClass是必须的参数它告诉Walk函数只返回要素类而不返回目录factoryCode通常是EPSG编号例如4490是CGCS2000地理坐标系4547是CGCS2000高斯-克吕格投影某分带。如果名称是“未定义”就说明数据缺少.prj需要回到第5章的处理方式。检查完质量之后还要做一次最终验证用投影后的岷江沱江水系shp计算总面积与流域公开资料里的控制断面集水面积做量级对比。具体做法是在ArcGIS中新建一个面积字段用“计算几何”功能按平方千米输出再对照相关水文手册里岷江、沱江的水文站控制流域面积。两者如果相差在合理范围内数据才算真正可用如果差出数倍说明数据边界或属性本身有问题这时用DEM重新划分边界比继续修shp更有价值。我自己经手这些数据时真正吃过没有校验的亏。某次拿一份来源不明的流域shp直接做了淹没范围估算后续对接时发现面积与官方数据差出不少核查后确认是边界数据被简化过整个前期成果全部返工。从那以后任何shp到我手里第一件事永远是跑一遍体检脚本、确认坐标系、做一次面积对比。这套流程不复杂但能在ArcGIS里少走很多弯路。希望帮到你。本文还有配套的精品资源点击获取