
简介本资源为全国地理分区SHP矢量数据集面向地理信息科学、城乡规划、水文气象及农业生态等方向的学习者与研究人员可用于空间分析、专题制图与区域研究。数据覆盖九大流域、三大地理分区、六大地理区域、气候区划、九大农业区分布及林业工程空间分布等图层并附shp2json.py脚本可将SHP批量转换为JSON便于在Python生态中进一步处理与可视化。压缩包共65个文件约40.48MB以shp、shx、dbf、prj等矢量核心文件为主辅以sbn、sbx空间索引、jpg预览图、xml元数据及zbak备份文件结构完整、开箱即用。目前已有209人学习下载。借助这些数据与脚本读者可快速搭建中国地理分区研究底图完成流域与气候区划叠加分析、农业与林业空间分布制图并掌握SHP转JSON的实用技巧为论文写作与项目开发提供可靠的数据支撑。1. 全国地理分区数据集三大分区、九大流域与气候区带怎么落到一张 SHP 里做空间分析的人大概都遇到过这种场景手头有一份全国气象站点数据想按「气候区带」做聚合统计结果发现站点只有经纬度没有分区字段或者拿到一份流域水文数据想按「九大流域」切片却找不到一份边界干净、属性齐全的矢量底图。这时候最省事的做法就是找一份现成的全国地理分区 SHP 矢量数据把三大分区、九大流域、气候区带这几套边界一次性拿到手用 Python 直接做空间连接。这份数据集解决的就是这个问题它把全国尺度的地理分区边界整理成标准 SHP 矢量格式覆盖三大分区、九大流域、气候区带三套体系配套 Python 代码做读取、投影转换和分区统计。适合做资源环境、气象水文、国土空间规划的从业者也适合刚接触空间数据、想拿一份真实全国边界练手的同学。下面按「数据是什么 → 怎么用 Python 跑通 → 坑在哪 → 进阶怎么玩」的顺序拆开讲。2. 三大分区、九大流域、气候区带三套边界体系的选型与字段结构2.1 为什么是这三套分区而不是随便找一份行政区划很多人第一反应是拿行政区划边界凑合但行政区划和自然地理分区是两套逻辑。行政区划按省市区县切边界跟着管理范围走而三大分区通常指东部、中部、西部这类经济地理划分、九大流域长江、黄河、珠江、松花江、辽河、海河、淮河、东南诸河、西南诸河等、气候区带温带、亚热带、热带等是按自然地理和经济地理属性切的边界往往跨省。如果你做的是气象插值、水文模拟、生态分区统计用行政区划会把同一气候带切得七零八落统计结果失真。这份数据集的价值就在于它把三套自然/经济地理边界都整理好了你可以按研究目标选对应图层而不是被迫用行政区划硬套。常见做法是做气候相关分析用气候区带图层做水资源分析用九大流域图层做区域经济对比用三大分区图层。三套图层坐标系一般统一到 CGCS2000 或 WGS84属性表里带分区名称、编码字段方便后续 join。2.2 SHP 文件的组成与字段含义一份标准 SHP 矢量数据不是单个文件而是一组同名文件文件后缀作用是否必须.shp存储几何形状点/线/面必须.shx几何索引加速查询必须.dbf属性表存分区名称、编码必须.prj投影坐标系定义强烈建议保留.cpg属性表字符编码说明建议保留属性表里通常有这几类字段分区名称如「长江流域」「亚热带」、分区编码数字或字母编码方便程序判断、可能还有面积、周长等几何字段。读取时用 Python 的 geopandas 最省事它能直接把 .shp 读成 GeoDataFrame属性表和几何一起拿到。提示如果拿到手的压缩包里只有 .shp 没有 .prj先别急着用坐标系不明会导致后续面积计算、空间连接全部错位。这种情况要么找原始来源补 .prj要么根据数据范围手动指定坐标系。2.3 三套图层的适用场景对照选哪套图层取决于你的分析目标。下面这张对照表可以帮你快速判断分区体系典型用途分区数量级边界特点三大分区区域经济对比、宏观政策研究3 个跨省边界较粗九大流域水文模拟、水资源统计9 个按水系划分边界精细气候区带气象插值、农业气候区划多个带按积温、降水划分如果你不确定用哪套一个简单判断看你的数据有没有「流域」属性有就用九大流域看有没有「气候带」属性有就用气候区带都没有、只想做东中西对比就用三大分区。3. 用 Python 读取 SHP 并做分区统计从环境配置到空间连接3.1 环境准备geopandas 安装与常见依赖问题geopandas 不是纯 Python 包它依赖 GDAL、Fiona、pyproj 这些 C 库直接 pip install 经常翻车。血泪经验是优先用 conda 装conda 会把依赖一起解决。# 推荐方式conda 创建独立环境 conda create -n geo python3.10 conda activate geo conda install -c conda-forge geopandas matplotlib如果你只能用 pip那就先装 GDAL 轮子再装 geopandas# pip 方式先确保 GDAL 版本匹配 pip install gdal$(gdal-config --version) pip install geopandas逻辑说明conda 的 conda-forge 频道维护了完整的空间分析依赖链装 geopandas 时会自动带上 Fiona、pyproj、shapely。pip 方式下 GDAL 版本必须和系统里已装的 GDAL 一致否则 import 时报 DLL 错误。参数上python3.10 是比较稳的版本3.11/3.12 部分轮子还没跟上。装完后验证import geopandas as gpd print(gpd.__version__)能打印版本号就说明环境通了。如果报ImportError: DLL load failed九成是 GDAL 版本冲突回退到 conda 方式。3.2 读取三套分区图层并检查坐标系import geopandas as gpd # 读取三套分区图层路径按实际解压位置改 basin gpd.read_file(./data/jiuda_liuyu.shp) # 九大流域 climate gpd.read_file(./data/qihou_qudai.shp) # 气候区带 region gpd.read_file(./data/sanda_fenqu.shp) # 三大分区 # 检查坐标系和字段 for name, gdf in [(流域, basin), (气候, climate), (分区, region)]: print(name, 坐标系:, gdf.crs) print(name, 字段:, list(gdf.columns)) print(name, 要素数:, len(gdf))逻辑说明gpd.read_file会自动读取 .prj 里的坐标系信息赋给gdf.crs。如果打印出来是None说明 .prj 缺失或损坏需要手动指定比如gdf.set_crs(EPSG:4326)。字段列表里重点看有没有分区名称和编码列后面空间连接要用。要素数能帮你判断数据是否完整比如九大流域应该是 9 个要素如果只有 3 个说明数据被裁剪过。参数上read_file默认读第一个图层如果 SHP 里有多图层少见需要指定layer参数。路径建议用相对路径方便整个项目打包迁移。3.3 把站点数据做空间连接落到分区字段假设你有一份站点 CSV带经纬度想给每个站点打上流域和气候带标签import pandas as pd from shapely.geometry import Point # 读站点数据假设列名是 lon, lat df pd.read_csv(./data/stations.csv) geometry [Point(xy) for xy in zip(df[lon], df[lat])] stations gpd.GeoDataFrame(df, geometrygeometry, crsEPSG:4326) # 统一坐标系避免连接错位 basin basin.to_crs(stations.crs) climate climate.to_crs(stations.crs) # 空间连接站点落在哪个流域/气候带 stations gpd.sjoin(stations, basin[[name, geometry]], howleft, predicatewithin) stations stations.rename(columns{name: basin_name}) stations gpd.sjoin(stations, climate[[name, geometry]], howleft, predicatewithin) stations stations.rename(columns{name: climate_zone}) print(stations[[lon, lat, basin_name, climate_zone]].head())逻辑说明sjoin是空间连接核心函数predicatewithin表示站点几何落在分区多边形内部才算匹配。howleft保证即使站点落在分区外也保留不会丢数据。两次 sjoin 分别打上流域和气候带标签注意第二次 sjoin 前要把第一次产生的索引列处理掉否则可能报重复列错误。参数上predicate还可以用intersects相交对于边界上的点更宽松。坐标系必须先统一to_crs把分区图层转到站点坐标系避免经纬度和投影坐标混用导致连接全空。这一步是新手最容易翻车的地方两个图层坐标系不一致sjoin 结果全是 NaN还找不到原因。3.4 按分区聚合统计并导出结果# 按流域统计站点数量 count_by_basin stations.groupby(basin_name).size().reset_index(namestation_count) print(count_by_basin) # 导出带分区标签的站点表 stations.drop(columnsgeometry).to_csv(./output/stations_with_zone.csv, indexFalse) # 导出分区边界为 GeoJSON方便在 GIS 软件里查看 basin.to_file(./output/basin.geojson, driverGeoJSON)逻辑说明groupby按分区名称聚合size()统计每组成员数reset_index把结果转回 DataFrame。导出 CSV 时去掉 geometry 列否则会多出一串 WKT 字符串。导出 GeoJSON 用to_filedriver 指定 GeoJSON方便 QGIS、ArcGIS 直接打开。参数上如果要做面积加权统计可以先用gdf.area算每个分区面积再和站点数做归一化。注意area算出来的单位取决于坐标系地理坐标系EPSG:4326算出来是平方度没有物理意义要算真实面积得先投影到等面积坐标系比如to_crs(EPSG:6933)。4. 避坑与排查SHP 读取、坐标系、空间连接的高频翻车点4.1 现象read_file 报「No such file or directory」但文件明明在原因SHP 是一组文件只复制了 .shp 没复制 .dbf/.shx或者路径里有中文/空格导致编码问题。解决确认同名文件齐全路径尽量用英文如果必须用中文路径Python 3 一般能处理但部分 GDAL 版本会出问题建议把数据放到纯英文目录下再读。4.2 现象sjoin 结果全是 NaN站点一个都没匹配上原因两个图层坐标系不一致或者站点经纬度写反了lon/lat 颠倒。解决先打印两个图层的crs和total_bounds看范围是否对得上。中国范围经度约 73-135纬度约 3-53如果 bounds 里出现 30-120 这种基本就是经纬度反了。统一坐标系后再 sjoin。4.3 现象面积计算结果大得离谱或小得离谱原因在地理坐标系下直接算 area单位是平方度不是平方米。解决先to_crs转到等面积投影比如 EPSG:6933全球等面积圆柱或 Albers 投影再算 area。这一步不做后续所有面积相关的统计都是错的。4.4 现象属性表中文乱码原因.dbf 文件的字符编码和读取时指定的编码不一致常见于老数据用 GBK新数据用 UTF-8。解决读取时指定编码gpd.read_file(path, encodinggbk)或encodingutf-8试一下哪个正常。如果 .cpg 文件存在geopandas 一般能自动识别没有就手动指定。4.5 现象分区边界有缝隙或重叠站点落在缝里变成 NaN原因不同来源的边界数据拼接时没做拓扑处理或者简化过度导致边界不吻合。解决对边界做一次buffer(0)修复自相交或者用unary_union合并后再切分。如果只是个别站点落在缝里可以把predicate改成intersects或者给站点做小缓冲buffer(0.001)再连接。5. 进阶玩法把 SHP 转 WKT、构建邻接矩阵与批量分区裁剪5.1 SHP 几何转 WKT方便入库和跨工具传递SHP 是文件格式很多数据库和 Web 服务更认 WKT 字符串。把分区边界转成 WKT 存进数据库后续查询和空间函数调用都方便# 把分区几何转成 WKT 字符串 basin[wkt] basin.geometry.apply(lambda g: g.wkt) # 导出成带 WKT 的 CSV方便导入数据库 basin.drop(columnsgeometry).to_csv(./output/basin_wkt.csv, indexFalse)逻辑说明g.wkt把 shapely 几何对象转成标准 WKT 文本apply逐行处理。导出时去掉 geometry 列只留 WKT 和属性字段。参数上如果几何特别复杂WKT 字符串会很长入库时字段类型要选 TEXT 而不是 VARCHAR(255)。5.2 用分区边界构建邻接矩阵做空间自相关、区域扩散分析时需要知道哪些分区相邻。用 geopandas 的touches判断邻接关系import numpy as np n len(basin) adj np.zeros((n, n), dtypeint) for i in range(n): for j in range(i 1, n): if basin.geometry.iloc[i].touches(basin.geometry.iloc[j]): adj[i, j] adj[j, i] 1 print(adj)逻辑说明touches判断两个几何是否相邻共享边界但不重叠。双重循环构建对称邻接矩阵adj[i,j]1表示第 i 和第 j 个分区相邻。参数上如果边界有微小缝隙导致 touches 判断失败可以先对几何做buffer(0.01)再判断。5.3 批量裁剪用分区边界切自己的研究区如果你有一份全国栅格或矢量研究数据想按九大流域分别裁出来import geopandas as gpd study gpd.read_file(./data/study_area.shp).to_crs(basin.crs) for name in basin[name].unique(): sub_basin basin[basin[name] name] clipped gpd.clip(study, sub_basin) clipped.to_file(f./output/clip_{name}.shp, encodingutf-8)逻辑说明gpd.clip用分区边界裁剪研究区输出每个流域的子集。循环里按分区名称筛选逐个裁剪导出。参数上clip要求两个图层坐标系一致所以先to_crs。导出时指定encodingutf-8避免中文文件名乱码。从那以后我每次拿到新的 SHP 数据都强制先跑一遍「打印 crs total_bounds 字段列表」三件套确认坐标系和范围没问题再往下做这一步省掉后面无数排查时间。希望帮到你。本文还有配套的精品资源点击获取