资讯详情

资讯详情

中国省级行政区划SHP数据实战:从坐标校验到批量出图全流程

简介这份中国省级SHP数据面向地理信息系统从业者、城乡规划研究人员、高校师生及数据分析爱好者提供覆盖全国范围的行政区划矢量底图可用于地图制作、空间分析、区域统计与可视化项目帮助解决缺少标准行政边界数据的问题。压缩包共21个文件约9.91MB以shp、shx、dbf、prj为核心分别承载几何图形、索引、属性表与坐标投影信息并配有sbn、sbx空间索引及xml元数据兼容ArcGIS、QGIS等主流平台。数据按省级、地市级、区县级分层组织涵盖北京、天津、河北、山西、内蒙古、辽宁、吉林、黑龙江、上海、江苏、浙江、安徽、福建、江西、山东、河南、湖北、湖南、广东、广西、海南、重庆、四川、贵州、云南、西藏、陕西、甘肃、青海、宁夏、新疆、台湾、香港等全部省级行政区便于按需裁剪与叠加分析。目前已有3432人学习下载适合需要快速获取规范行政边界、开展空间制图与统计研究的用户参考使用。1. 省级边界 SHP 拿到手之后先搞清楚它到底能干什么做 GIS 的人大概都有过这种经历项目排期压到只剩三天底图还没着落甲方一句“先出个全国示意图”丢过来你打开 ArcGIS 发现手头只有一份分辨率惨不忍睹的在线底图导出即糊。这时候一份干净的中国省级行政区划 SHP 就是救命稻草。它本质上是一组矢量面数据每个要素代表一个省级行政单元属性表里通常挂着省名、行政代码、简称这类字段几何类型是 Polygon 或 MultiPolygon坐标系常见的是 WGS84 地理坐标或 CGCS2000。能解决的核心问题就三类出图底图、空间统计的统计单元、以及和其他图层做叠加分析时的裁剪框。适合谁用做专题制图的、跑空间自相关的、搞区域经济研究的、还有需要把业务数据按省聚合再落到地图上的开发同学。它不是万能的比如你要做区县级分析省级面太粗要做路网分析它没有线要素。但在“省级”这个粒度上它是很多流程的起点。2. 坐标系与字段结构拿到 SHP 先别急着拖进软件2.1 为什么坐标系判断错了后面全白干SHP 本身不强制存坐标系但配套的 .prj 文件会记录投影信息。很多网上流传的省级边界包.prj 要么缺失要么写的是 GCS_WGS_1984但实际坐标值却是投影后的米制坐标。这种“表里不一”的数据你直接拖进 ArcGIS 或 QGIS它会按 .prj 声明的坐标系去渲染结果要么位置偏到太平洋要么形状被拉伸得没法看。判断方法很简单看坐标数值的量级。经纬度坐标的 X 值在 73 到 135 之间Y 值在 3 到 54 之间如果是投影坐标数值通常是六位数甚至七位数。我一般会先用一个轻量脚本把范围打出来心里有数再决定要不要重新定义投影。import shapefile # 需要 pyshp 库pip install pyshp sf shapefile.Reader(china_province.shp) # 打印前五个要素的边界范围 for i, shp in enumerate(sf.shapes()[:5]): print(f要素 {i} 的 bbox: {shp.bbox}) # bbox 返回 [xmin, ymin, xmax, ymax] # 如果 xmin 在 70~140 之间基本可判定是经纬度坐标 # 如果 xmin 是 3xxxxx 或 1xxxxxx说明是投影坐标需要查 .prj 确认投影带这段代码的逻辑是不依赖任何桌面软件直接用 pyshp 读几何的包围盒。参数上没什么可调的关键是看输出。如果 bbox 的 X 范围落在 70 到 140 之间那基本就是地理坐标系单位是度如果 X 是几万到几十万那单位是米得去找对应的投影带号。常见做法是如果 .prj 缺失但数值是经纬度就手动指定 EPSG:4326如果数值是米制且大致对应中国区域可能是 CGCS2000 的高斯投影需要根据中央经线反推带号。2.2 属性表里哪些字段真正有用省级 SHP 的属性表字段五花八门有的包给的是中文省名有的给拼音有的给行政代码还有的塞了一堆面积、人口之类的冗余字段。真正做空间连接或分组统计时最稳的关联键是行政代码因为省名可能有“省”“自治区”“特别行政区”等后缀差异拼音也有多音字问题。我一般会先看一眼字段列表和几条记录确认代码字段的位数——省级代码通常是六位前两位代表省后四位是 0000 或者具体到地级市。如果只有省名没有代码那就得自己做一张映射表把“内蒙古自治区”和“内蒙古”这种别名统一掉否则后面按省聚合时会出现同一个省分成两条记录的血泪教训。# 查看字段名和前三条记录 fields [f[0] for f in sf.fields[1:]] # 跳过 DeletionFlag print(字段列表:, fields) records sf.records()[:3] for rec in records: print(dict(zip(fields, rec))) # 重点关注是否有 adcode / code / 行政代码 这类字段 # 以及省名字段是中文还是拼音有没有“省”字后缀逻辑说明sf.fields 的第一个元素是 DeletionFlag必须跳过。records() 返回的是列表每条记录是一个列表和字段顺序一一对应。参数上如果你发现代码字段是数值类型而不是字符串要小心前导零丢失的问题——比如“110000”可能被读成 110000虽然数值上一样但做字符串匹配时会出问题。常见做法是统一转成字符串再补零到六位。2.3 几何有效性检查别等到做叠加分析才翻车省级边界数据最常见的几何问题是自相交、悬挂节点和面重叠。这些问题在单纯出图时看不出来但一旦做 Intersect 或 Union 就会报错或者产生碎屑面。我一般会在正式用之前跑一遍几何有效性检查QGIS 里有“检查有效性”工具代码里可以用 shapely 的 is_valid 批量判断。如果发现无效几何优先用 buffer(0) 做修复而不是直接删掉因为省级面删一个就少一块。from shapely.geometry import shape from shapely.validation import explain_validity for i, shp in enumerate(sf.shapes()): geom shape(shp.__geo_interface__) if not geom.is_valid: print(f要素 {i} 无效: {explain_validity(geom)}) # 常见输出Self-intersection at or near point ... # 修复方式geom geom.buffer(0)参数说明buffer(0) 是一个经典技巧它会把自相交的环重新构造成合法多边形但对 MultiPolygon 可能会合并相邻部分所以修复后要检查面积变化是否在可接受范围内。如果面积变化超过 1%建议手动定位问题节点而不是无脑修复。3. 从 SHP 到可用底图投影、裁剪与格式转换的实操链路3.1 按出图需求选投影别一套 WGS84 走天下很多人拿到 SHP 就直接用 WGS84 出图结果中国地图被拉得又扁又长因为经纬度坐标在平面显示时高纬度地区会被拉伸。正确的做法是根据出图范围选投影。全国图常用 Albers 等面积投影参数是中央经线 105°E双标准纬线 25°N 和 47°N。分省图可以用对应省份的中央经线做高斯-克吕格投影。在 QGIS 里重投影就是“导出 → 另存为”选目标 CRS在 ArcGIS 里用 Project 工具。代码里用 pyproj 做转换也很直接。import pyproj from shapely.ops import transform from shapely.geometry import shape # 定义 Albers 投影适合全国范围 albers pyproj.CRS.from_proj4( projaea lat_125 lat_247 lat_00 lon_0105 x_00 y_00 datumWGS84 unitsm no_defs ) wgs84 pyproj.CRS.from_epsg(4326) project pyproj.Transformer.from_crs(wgs84, albers, always_xyTrue).transform # 对单个几何做投影转换 geom_wgs shape(sf.shapes()[0].__geo_interface__) geom_albers transform(project, geom_wgs) print(投影后面积平方米:, geom_albers.area)逻辑说明pyproj.Transformer 的 always_xyTrue 保证输入输出都是 (x, y) 顺序避免经纬度颠倒。参数上lat_1 和 lat_2 是双标准纬线选 25 和 47 是因为中国陆地大致在这个纬度范围内等面积特性最好。lon_0105 是全国图常用的中央经线。如果你只做某个省比如四川中央经线可以改成 105 或 102标准纬线也相应调整。3.2 用省级面做裁剪框Clip 和 Intersect 的区别当你有一份全国河流数据只想保留某个省内的部分就需要用省级面去裁剪。ArcGIS 里 Clip 和 Intersect 都能做但行为不同Clip 只保留输入要素落在裁剪框内的部分属性表还是原来的Intersect 会保留两者属性但可能产生更多要素。我一般做底图裁剪用 Clip做空间统计用 Intersect。QGIS 里对应“矢量 → 地理处理工具 → 裁剪”。代码里用 geopandas 的 clip 最省事。import geopandas as gpd provinces gpd.read_file(china_province.shp) rivers gpd.read_file(rivers.shp) # 选出四川省 sichuan provinces[provinces[name].str.contains(四川)] # 用四川省边界裁剪河流 rivers_in_sichuan gpd.clip(rivers, sichuan) rivers_in_sichuan.to_file(rivers_sichuan.shp, encodingutf-8)参数说明gpd.clip 的第二个参数可以是 GeoDataFrame 或单个几何。如果 provinces 的坐标系和 rivers 不一致clip 会报错所以前面必须先统一 CRS。encodingutf-8 是为了保证中文属性在导出时不乱码这个坑在 Windows 上尤其常见。3.3 转成 GeoJSON 或 WKT给前端和数据库用SHP 是桌面软件的老朋友但前端地图库和数据库更认 GeoJSON 或 WKT。转换时要注意坐标系和精度。GeoJSON 规范要求用 WGS84 经纬度所以如果你之前投影到了 Albers转 GeoJSON 之前得转回 4326。WKT 则没有坐标系强制要求但入库时最好和数据库表的 SRID 对齐。# SHP 转 GeoJSON provinces_wgs provinces.to_crs(epsg4326) provinces_wgs.to_file(china_province.geojson, driverGeoJSON) # 导出为 WKT 字符串用于入库 provinces_wgs[wkt] provinces_wgs.geometry.apply(lambda g: g.wkt) provinces_wgs[[name, wkt]].to_csv(province_wkt.csv, indexFalse)逻辑说明to_crs 做坐标系转换driverGeoJSON 指定输出格式。WKT 导出时geometry 的 wkt 属性直接给出字符串。参数上如果几何特别复杂WKT 字符串可能非常长入库时要注意字段类型用 TEXT 或 CLOB别用 VARCHAR 限长。常见做法是先用 simplify 做适当简化比如 tolerance0.01 度能大幅减小体积且肉眼几乎看不出差别。4. 避坑与排查省级 SHP 用起来最容易翻车的五个地方4.1 中文属性乱码现象是省名显示成问号或方块原因通常是 SHP 的 .dbf 文件编码和软件默认编码不一致。ArcGIS 对 UTF-8 支持较晚很多老数据是 GBK 编码。解决方法是先在 QGIS 里看属性表是否正常如果 QGIS 正常而 ArcGIS 乱码就在 ArcGIS 里用“转换编码”工具或者直接改注册表。更稳的做法是用 geopandas 读进来时指定 encodinggbk 或 utf-8导出时统一用 utf-8。4.2 面积计算出来是负数或零现象是投影后面积字段异常原因多半是几何环的方向不对SHP 规范要求外环顺时针、内环逆时针但有些数据反了。解决方法是读进来后用 shapely 的 orient 函数修正方向或者直接用 abs(area) 取绝对值。如果面积是零检查是不是把线要素误当成了面。4.3 空间连接后一个省出现多条记录现象是统计结果翻倍原因通常是省级面有重叠或者被连接的点数据落在边界上被两个省同时捕获。解决方法是先做几何有效性检查和重叠检测然后用“空间连接”时选“一对一”而不是“一对多”或者加一个距离阈值做最近匹配。4.4 导出 GeoJSON 后前端加载慢现象是浏览器卡顿原因是省级边界的节点太密一个省可能几十万个点。解决方法是做几何简化用 Douglas-Peucker 算法tolerance 根据显示级别定全国图 0.01 度足够分省图可以到 0.001 度。简化后体积能降一个数量级。4.5 和 DEM 提取的 shp 叠加时对不上现象是边界错位原因通常是 DEM 提取的 shp 用的是投影坐标而省级 SHP 是地理坐标两者没统一。解决方法是先确认两者的 CRS把地理坐标的那个投影到和另一个一致或者都转成 4326 再做叠加。别小看这一步我见过有人在这上面耗了一整天。5. 进阶技巧用省级 SHP 做渔网分割与批量出图5.1 渔网分割把省域切成规则网格做空间抽样做空间分析时经常需要把研究区切成规则网格比如 10km×10km 的渔网然后统计每个网格里的点数量。用省级 SHP 做渔网关键是先投影到米制坐标系再用 create_grid 或者自己写循环生成。QGIS 里有“创建网格”工具代码里可以用 shapely 的 box 配合 numpy 生成。import numpy as np from shapely.geometry import box import geopandas as gpd # 假设 sichuan_albers 是投影后的四川省单位米 minx, miny, maxx, maxy sichuan_albers.total_bounds cell_size 10000 # 10km # 生成网格中心点或网格面 cols np.arange(minx, maxx, cell_size) rows np.arange(miny, maxy, cell_size) cells [box(x, y, x cell_size, y cell_size) for x in cols for y in rows] # 只保留与省域相交的网格 grid gpd.GeoDataFrame(geometrycells, crssichuan_albers.crs) grid gpd.overlay(grid, sichuan_albers, howintersection) grid.to_file(sichuan_grid.shp, encodingutf-8)逻辑说明total_bounds 返回投影后的范围单位是米。cell_size 根据研究尺度定做省级抽样一般 5km 到 20km 都有人用。overlay 的 howintersection 保证只保留落在省域内的网格边缘会被裁剪成不规则形状。参数上如果网格数量太大比如超过十万建议改用点网格或者降低分辨率否则后续空间连接会很慢。5.2 批量出图一个省一张图自动加标题和指北针做区域报告时经常需要每个省出一张图。手动在 ArcGIS 里重复三十多次是折磨用 Python 的 matplotlib 配合 geopandas 可以批量搞定。关键是设置好中文字体否则标题全是方块。import matplotlib.pyplot as plt import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei] # 中文字体 matplotlib.rcParams[axes.unicode_minus] False provinces gpd.read_file(china_province.shp) for idx, row in provinces.iterrows(): fig, ax plt.subplots(figsize(8, 6)) gpd.GeoSeries([row.geometry]).plot(axax, color#f0f0f0, edgecolorblack) ax.set_title(row[name], fontsize16) ax.axis(off) fig.savefig(foutput/{row[name]}.png, dpi150, bbox_inchestight) plt.close(fig)参数说明font.sans-serif 指定中文字体Windows 上用 SimHeiLinux 上可以用 WenQuanYi 或 Noto Sans CJK。dpi150 保证出图清晰度bbox_inchestight 去掉多余白边。如果某个省有多个多边形比如海岛GeoSeries 会自动处理。这个脚本跑一遍三十多张图几分钟就出来了比手动操作省下的时间够你喝好几杯咖啡。从那以后我每次拿到新的 SHP 数据都强制走一遍“看 bbox → 查字段 → 验几何 → 统一 CRS”这四步再也没出现过拖进软件才发现坐标不对的尴尬。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →