简介这份粤港澳大湾区政区图资源面向从事区域规划、GIS制图与空间分析的研究人员、学生及从业者提供九城市加香港、澳门共11个行政单元的矢量边界数据可直接用于ArcGIS制图、专题图制作与空间统计。压缩包共7个文件约270KB包含shp主文件、shx索引、dbf属性表、prj投影定义以及sbn、sbx空间索引和xml元数据覆盖矢量数据完整组成导入后即可正常渲染与查询。数据依据广东省自然资源厅1:100万行政区划图自行制作并非网络拷贝其中海岸线部分耗费了作者九成时间边界细节相对可靠。目前已有4362人学习下载适合需要快速获取大湾区政区底图、开展区域对比或叠加分析的读者省去自行描边与配准的重复劳动。1. 从一份「92」政区图压缩包说起它到底能解决什么问题做区域规划、物流选址、应急调度或者招商汇报的人大概率都遇到过同一个尴尬手头有一份全国行政区划数据但一放大到某个城市群边界就糊成一团街道级、区县级的界线要么缺失要么和最新的行政区划调整对不上。尤其是涉及跨城市协同分析时把十几个城市的矢量边界拼在一起坐标系不统一、属性字段命名混乱、飞地漏画几乎是家常便饭。标题里的「粤港澳大湾区政区图92」说的就是把这个特定区域——九个珠三角城市加上两个特别行政区——的行政边界整理成一份可以直接进 GIS 或可视化工具的数据包。它解决的不是「画一张好看的地图」这种表面需求而是给后续的空间统计、缓冲区分析、热力叠加提供一个几何正确、层级清晰、属性可关联的底图。适合谁用做城市研究的数据分析师、做区域业务拓展的运营、做汇报材料的产品经理以及需要把行政边界当空间筛选条件的后端开发。这份数据的价值不在「图」本身而在于它把「92」这个特定口径固化成了一个可复用的空间对象。2. 政区图数据包的内部结构图层、字段与坐标系的选型逻辑拿到一个政区图压缩包第一件事不是急着打开看而是先搞清楚它里面到底装了什么。很多人翻车就翻在这里以为解压出来一个 shp 就能用结果发现属性表里全是乱码或者坐标系是投影坐标套到在线地图上偏了几百米。这一章把数据包的典型构成拆开讲顺带说清楚为什么这样组织。2.1 从压缩包到图层常见格式与目录组织政区图类数据包常见做法是打包成 Shapefile 或 GeoJSON 两种格式之一少数会附带 KML 用于快速预览。Shapefile 是一组文件的集合单独一个.shp是打不开的必须和.shx、.dbf、.prj放在同一目录下。GeoJSON 则是单文件适合直接丢进前端或 Python 读取。一个组织良好的「92」数据包目录结构通常长这样gba_admin/ ├── gba_city.shp # 城市/特别行政区级边界 ├── gba_city.shx ├── gba_city.dbf ├── gba_city.prj ├── gba_district.shp # 区县级边界 ├── gba_district.shx ├── gba_district.dbf ├── gba_district.prj └── gba_admin.geojson # 合并版便于快速加载如果你拿到的包只有 shp 没有 prj那就要警惕了——没有投影文件坐标系只能靠猜。常见做法是先用 GIS 软件打开看一眼形状再根据经纬度范围反推。下面这段 Python 代码可以快速检查一个 Shapefile 的坐标系和字段import geopandas as gpd # 读取城市级边界注意路径指向 .shp 文件 gdf gpd.read_file(gba_admin/gba_city.shp) # 打印坐标系信息EPSG:4326 表示 WGS84 经纬度 print(CRS:, gdf.crs) # 查看属性表字段和前几行确认名称字段是否可读 print(gdf.columns.tolist()) print(gdf.head()) # 检查几何类型政区图通常是 Polygon 或 MultiPolygon print(Geometry types:, gdf.geom_type.unique())这段代码的逻辑很直接先确认坐标系再确认字段最后确认几何类型。参数上唯一需要注意的是路径Windows 下反斜杠要转义或改用正斜杠。如果gdf.crs返回None说明缺少 prj 文件这时候不要硬套先根据数据来源判断是 WGS84 还是 CGCS2000两者在珠三角区域的差异虽然不大但做精确面积统计时不能混用。2.2 属性字段设计怎么让边界能跟业务数据关联政区图能不能用一半看几何一半看属性。几何再准如果属性表里只有一个NAME字段你想按行政区代码关联人口、GDP、订单量就无从下手。一个合格的「92」数据包属性字段至少应该包含以下几类字段名含义示例值用途adcode行政区划代码440300与统计年鉴、业务表关联name名称某市展示与筛选level层级city / district区分城市与区县parent上级代码440000构建层级关系region区域标签92标记是否属于大湾区口径这里要特别提醒adcode字段。行政区划代码是六位数字前两位是省级中间两位是市级后两位是区县。做关联时如果业务数据里存的是名称而不是代码就会出现「某市」和「某市市」对不上的情况。我一般会建议在数据包里同时保留代码和名称并且在导入业务库时以代码为准做 join名称只用于展示。2.3 坐标系选择WGS84、CGCS2000 与 Web 墨卡托的取舍坐标系是政区图里最容易埋雷的地方。三种坐标系各有适用场景WGS84EPSG:4326GPS 原始坐标经纬度单位适合做跨平台交换和存储。CGCS2000EPSG:4490国家大地坐标系和 WGS84 在珠三角区域差异在厘米级做国内正式成果时优先用这个。Web 墨卡托EPSG:3857在线地图底图用的投影单位是米适合做面积计算和前端叠加但高纬度会变形。常见做法是数据包以 WGS84 或 CGCS2000 存储做面积统计时临时投影到适合该区域的投影坐标系比如珠三角可以用 UTM 50NEPSG:32650。下面这段代码演示了从 WGS84 转到 UTM 50N 再算面积的过程import geopandas as gpd gdf gpd.read_file(gba_admin/gba_city.shp) # 先确认原始坐标系是地理坐标 print(原始 CRS:, gdf.crs) # 投影到 UTM 50N单位变为米适合算面积 gdf_utm gdf.to_crs(epsg32650) # 计算每个城市的面积单位平方公里 gdf_utm[area_km2] gdf_utm.geometry.area / 1e6 print(gdf_utm[[name, area_km2]])参数说明to_crs里的epsg32650是 UTM 50N 的代码覆盖东经 114 到 120 度珠三角正好在范围内。如果你的数据里包含更靠西的城市可能需要换成 49N。面积除以 1e6 是把平方米转成平方公里。这一步做完你就能拿面积字段去和统计公报里的数据做交叉验证如果偏差超过 5%大概率是边界版本太旧或者投影选错了。3. 用 Python 把「92」政区图跑通加载、筛选与空间叠加数据包结构清楚了接下来就是动手。这一章的目标是让你能在本地用 Python 把这份政区图加载进来按「92」口径筛选再和业务点数据做一次空间叠加。整个过程不需要装 QGIS 或 ArcGIS纯代码就能跑。3.1 环境准备与依赖安装先确认 Python 版本在 3.8 以上然后装三个核心库geopandas、shapely、pyproj。geopandas 负责读写和空间操作shapely 提供几何对象pyproj 处理坐标系转换。用 conda 装最省事因为 geopandas 依赖 GDALpip 直接装容易编译失败。# 用 conda 创建独立环境避免和系统库冲突 conda create -n gba_map python3.10 conda activate gba_map # 从 conda-forge 频道安装依赖会自动解决 conda install -c conda-forge geopandas shapely pyproj matplotlib如果你只能用 pip那就先装 GDAL 的 wheel 包再装 geopandas但版本匹配很折腾血泪经验是能 conda 就 conda。装完之后跑一句import geopandas不报错环境就算通了。3.2 加载边界并按「92」口径筛选假设数据包里城市级图层已经包含了「92」全部对象但你可能只想保留其中某几个城市做分析。下面这段代码演示了加载、查看、筛选的完整流程import geopandas as gpd # 加载城市级边界 cities gpd.read_file(gba_admin/gba_city.shp) # 先看看有哪些城市确认名称字段 print(cities[[adcode, name, region]].to_string()) # 按 region 字段筛选出大湾区口径的对象 gba cities[cities[region] 92].copy() # 如果数据包里没有 region 字段就按 adcode 前缀或名称列表筛选 target_codes [440100, 440300, 440400, 440500, 440600, 441200, 441300, 441900, 442000, 810000, 820000] gba_by_code cities[cities[adcode].isin(target_codes)].copy() print(筛选后对象数:, len(gba_by_code))逻辑说明优先用region字段筛选因为这是数据包作者预置的口径最省事。如果没有这个字段就用adcode列表匹配。参数上要注意adcode在 dbf 里可能是字符串也可能是数字如果是数字isin里的列表也要用数字否则匹配不上。筛选完记得.copy()避免后续修改触发 pandas 的警告。3.3 点数据空间叠加判断业务点落在哪个城市政区图最常用的操作之一是拿一批带经纬度的业务点判断每个点落在哪个行政区。比如你有一批门店坐标想知道每个城市各有多少家。下面这段代码用sjoin完成空间连接import pandas as pd import geopandas as gpd from shapely.geometry import Point # 构造示例业务点实际使用时从 CSV 读取 df pd.DataFrame({ shop_id: [S001, S002, S003], lng: [113.93, 114.06, 113.55], lat: [22.53, 22.54, 22.20] }) # 把经纬度转成几何点注意先建 DataFrame 再转 GeoDataFrame geometry [Point(xy) for xy in zip(df[lng], df[lat])] points gpd.GeoDataFrame(df, geometrygeometry, crsEPSG:4326) # 确保边界和点的坐标系一致 gba gba.to_crs(points.crs) # 空间连接predicatewithin 表示点落在面内 joined gpd.sjoin(points, gba[[name, adcode, geometry]], howleft, predicatewithin) print(joined[[shop_id, name, adcode]])逻辑说明sjoin的核心参数是predicatewithin表示点完全落在面内intersects表示只要相交就算。政区图边界通常有共享边用within更严格避免边界上的点被重复匹配。howleft保证没有匹配上的点也保留方便排查是不是坐标写错了。参数上crs必须两边一致否则sjoin会报错或给出错误结果。这一步跑通你就能按城市聚合业务点了。3.4 出图验证快速渲染检查边界完整性代码跑完最好出一张图肉眼检查一下尤其是飞地和岛屿有没有漏。下面这段代码用 matplotlib 渲染import matplotlib.pyplot as plt fig, ax plt.subplots(figsize(10, 8)) # 绘制边界facecolor 设为浅色edgecolor 设为深色 gba.plot(axax, facecolor#e8f0fe, edgecolor#1a73e8, linewidth0.8) # 叠加业务点红色小点 points.plot(axax, colorred, markersize10) # 去掉坐标轴出图更干净 ax.set_axis_off() plt.title(GBA Admin Boundary with Points) plt.savefig(gba_check.png, dpi150, bbox_inchestight)参数说明figsize控制画布大小dpi控制清晰度bbox_inchestight去掉多余白边。出图后重点看三处海岸线是否连续、岛屿是否完整、相邻城市之间有没有缝隙或重叠。如果发现某个区县缺失回到属性表检查是不是筛选条件把它排除了。4. 避坑与排查政区图使用中最容易翻车的五个地方这一章是我自己踩过的坑按「现象 → 原因 → 解决」整理。每一条都对应真实场景不是理论推演。4.1 现象地图整体偏移几百米套在线底图上对不齐原因坐标系被误判。很多数据包标注是 WGS84实际可能是 CGCS2000 或者某个地方坐标系两者在珠三角差异虽小但如果数据经过二次投影又没更新 prj就会偏。更常见的是把 Web 墨卡托的数据当成 WGS84 用纬度越高偏移越大。解决先用gdf.crs看声明再用gdf.total_bounds看经纬度范围。如果范围是[113, 22, 115, 24]这种基本是地理坐标如果是[1.2e7, 2.5e6, ...]这种大数就是投影坐标。确认后统一转成 EPSG:4326 再做叠加。如果还是偏拿一个已知地标比如某个知名建筑的经纬度去比对反推偏移量。4.2 现象属性表里的中文全是乱码原因Shapefile 的 dbf 文件默认编码是 GBK 或 Latin-1而 geopandas 默认按 UTF-8 读编码不匹配就乱码。解决读取时指定编码gpd.read_file(xxx.shp, encodinggbk)或encodinglatin-1。如果还是乱码用encodingutf-8试一遍。实在不行用 QGIS 打开另存为 GeoJSONGeoJSON 默认 UTF-8能绕过 dbf 的编码问题。4.3 现象相邻城市边界之间有缝隙做叠加分析时出现空白带原因不同城市的边界是分别数字化再拼接的顶点没有对齐导致共享边不重合。这在跨城市做缓冲区分析时尤其明显。解决做一次拓扑修复。常见做法是用shapely的unary_union把所有面合并再打散或者用geopandas的buffer(0)消除自相交。但要注意buffer(0)会轻微改变几何形状做精确面积统计前要评估影响。更稳妥的做法是找一份已经做过拓扑检查的数据源。4.4 现象飞地或岛屿在图上消失原因筛选时按属性字段过滤把飞地所属的区县排除了或者数据源本身就没有收录离岛。解决先不做任何筛选全量渲染一遍确认数据源里有没有这些几何。如果数据源有但筛选后没了检查筛选条件是不是只匹配了主城区。如果数据源本身没有那就只能换数据源或者手动补录。4.5 现象面积统计结果和官方公布数据差很多原因投影选错导致面积变形或者边界版本太旧行政区划调整后面积变了。解决确认投影坐标系是否适合该区域珠三角用 UTM 50N。然后核对数据版本的时效性行政区划调整频繁的区域边界数据可能一年就变一次。最后官方面积通常包含水域和海域而矢量边界可能只算了陆域口径不同也会导致差异。5. 进阶技巧把政区图变成可复用的空间筛选服务前面讲的都是单次分析如果你需要反复用这份「92」政区图做筛选比如后端接口要根据用户传入的经纬度返回所属城市每次都读 shp 文件就太慢了。这一章讲两个进阶做法一是把边界数据转成轻量格式做快速查询二是用空间索引加速点面匹配。5.1 转成 GeoJSON 或 GeoPackage 做持久化Shapefile 的读取速度受限于 dbf 和 shx 的解析转成 GeoPackage.gpkg或 GeoJSON 后读取会快不少。GeoPackage 是 SQLite 数据库支持空间索引适合数据量大时用。转换命令很简单import geopandas as gpd gdf gpd.read_file(gba_admin/gba_city.shp) # 转成 GeoPackage图层名设为 gba_city gdf.to_file(gba_admin.gpkg, layergba_city, driverGPKG) # 也可以转成 GeoJSON方便前端直接加载 gdf.to_file(gba_admin.geojson, driverGeoJSON)参数说明driverGPKG是 GeoPackage 的驱动名layer指定图层名一个 gpkg 可以存多个图层。GeoJSON 不需要指定 layer但文件体积会比 gpkg 大因为它是文本格式。如果边界顶点特别密可以先做一次简化gdf.simplify(0.001)能在几乎不影响视觉效果的前提下减小体积。5.2 用空间索引加速点面匹配当业务点数量到几万甚至几十万时sjoin的全量比对会变慢。geopandas 底层用的是 rtree 空间索引但如果你在循环里反复查询还是建议手动建索引。下面这段代码演示了用shapely的STRtree做快速查询from shapely.strtree import STRtree from shapely.geometry import Point # 构建空间索引传入几何列表 geoms gba.geometry.tolist() tree STRtree(geoms) # 查询单个点落在哪个面内 test_point Point(113.93, 22.53) idx tree.query(test_point) # idx 返回的是候选几何的索引还需要精确判断 for i in idx: if geoms[i].contains(test_point): print(所属城市:, gba.iloc[i][name]) break逻辑说明STRtree先做粗筛返回可能相交的几何索引再用contains做精确判断。这样比全量遍历快一个数量级。参数上注意query返回的是索引数组不是几何对象要用gba.iloc[i]去取属性。如果点特别多可以把查询逻辑封装成函数配合多进程批量处理。5.3 一个容易忽略的细节边界共享与重复计算做点面匹配时如果两个城市共享一条边界而点正好落在边界上contains可能返回 False因为contains不包含边界。这时候要用intersects或者covers。但intersects又可能导致一个点被两个城市同时匹配。我的习惯是先用contains匹配不到再用intersects兜底并且在业务上约定边界点归属规则比如按经度或纬度取小者。这个细节在门店归属、网格化管理场景里经常引发扯皮提前定好规则比事后修数据省事得多。最后说个我自己的教训早期做区域分析时我直接拿网上下载的政区图就用结果因为边界版本太旧某个新设的区没被包含进去导致整份报告的数据对不上。后来我养成了一个习惯任何空间数据拿到手先做三件事——看坐标系、看字段、看边界完整性确认无误再进分析流程。这个习惯帮我省下了不少返工时间。希望帮到你。本文还有配套的精品资源点击获取