
简介这份资源面向地理信息系统从业者、城市规划研究者及高校师生提供中国全部地级市行政区域的空间边界数据可用于城市分布研究、人口统计、行政边界划分与专题制图等场景帮助使用者在ArcGIS中完成裁剪、合并等空间分析操作。压缩包共11个文件约1.91MB以Shapefile标准文件组为主shp存储行政区域几何边界dbf保存城市名称、代码、人口、面积等属性prj定义坐标系统shx、sbn、sbx承担索引与快速检索功能另有xml元数据及若干lock临时文件。数据年代为2004年字段与边界信息完整可直接导入GIS软件进行可视化与统计分析。目前已有2079人学习下载适合需要基础市级行政区划底图、开展空间分析练习或搭建研究数据框架的读者参考使用。1. 市级行政区域 shp 到底解决什么问题从一张对不上的地图说起做数据可视化的人大概都遇到过这种场面业务方甩来一份门店清单字段里只有“城市名”你兴冲冲地往地图上一贴结果发现同一个“市”在底图上要么找不到要么落到了隔壁省。问题往往不在数据而在底图——你手里那份市级行政区域 shp 的行政区划口径和业务数据用的口径根本不是一套。市级行政区域 shp 格式说白了就是把全国地级行政单元的边界以 shapefile 这种 GIS 通用矢量格式存下来每个面要素带一个城市名和行政代码。它能解决的核心问题就一个让“城市”这个模糊的文字概念变成地图上可计算、可叠加、可做空间统计的多边形。适合谁做区域业务分析、门店选址、物流分区、大屏可视化的从业者以及需要把业务表按城市聚合再落到地图上的数据工程同学。这一章先把“它是什么、为什么是 shp、口径为什么是最大的坑”讲透后面再动手。2. 市级行政区域 shp 的字段结构与选型为什么不是随便下一份就能用2.1 shapefile 不是单个文件四个兄弟缺一不可很多人第一次拿到 shp 会懵解压出来一堆同名不同后缀的文件到底哪个是数据shapefile 是 ESRI 定义的一种矢量数据交换格式它本质是一个文件集合而不是一个文件。真正干活的是下面这几个后缀作用缺失后果.shp存几何图形点线面坐标没有几何直接打不开.shx几何索引加速定位部分软件能重建但读取会变慢甚至报错.dbf属性表存城市名、行政代码等字段只剩空壳面没有名字.prj坐标系定义WGS84、CGCS2000 等坐标对不上叠加时整体偏移血泪经验是只拷贝 .shp 发给同事对方打开是一片空白或者属性全空八成就是漏了 .dbf 和 .prj。所以传输时永远打包整个同名文件组别挑单个文件。另外 .cpg 文件管的是 dbf 的字符编码中文城市名乱码时先看它。2.2 市级口径的三种来源选错等于白干“市级”这两个字在不同数据源里含义不一样这是最容易翻车的地方。常见的有三类口径地级行政区口径包含地级市、自治州、地区、盟这是统计年鉴和大多数业务分析默认的口径要素数量在三百多个量级。地级市口径只保留“市”把自治州、地区排除数量会少一截做“城市排名”类分析时常用。市辖区口径把地级市拆成区粒度更细适合做城市内部的分区分析但和“按城市汇总”的业务表对不上。选型原则很简单先看你的业务表里“城市”字段是怎么来的。如果是从订单地址里抽的“XX市”那大概率对应地级市口径如果是统计报表里的“XX地区”就得用地级行政区口径。口径不统一后面做空间连接时会出现大量匹配失败或者一个城市被拆成好几块。我一般会先拿业务表里的城市名去和 shp 的属性表做一次交集统计匹配率低于九成就要回头查口径而不是硬着头皮往下做。2.3 坐标系WGS84 和 CGCS2000 别混着用市级行政区域 shp 常见的坐标系有两种WGS84EPSG:4326经纬度和 CGCS2000国家大地坐标系EPSG:4490。两者在多数业务场景下差异很小但如果你要和其他图层比如 GPS 点位、卫星影像叠加坐标系必须一致否则会出现几十米到几百米的偏移。判断方法看 .prj 文件内容或者用 GIS 软件打开后看图层属性里的 CRS。做 Web 地图展示时通常还要再投影到 Web 墨卡托EPSG:3857这一步在代码里做不要提前改源文件保留原始经纬度版本作为底稿。3. 用 Python 把市级 shp 读进来并做一次城市匹配3.1 环境准备与最小读取先装依赖。geopandas 是读 shp 最顺手的库底层依赖 fiona 和 pyproj用 conda 或 pip 都能装。下面是最小可运行代码import geopandas as gpd # 读取市级行政区域 shp注意路径指向 .shp 文件即可 gdf gpd.read_file(./data/city_boundary.shp) # 看前几行属性确认字段名 print(gdf.columns.tolist()) print(gdf.head()) # 看坐标系 print(gdf.crs) # 看要素数量和几何类型 print(len(gdf), gdf.geom_type.unique())逻辑说明read_file会自动关联同名的 .dbf、.shx、.prj所以只要路径对四个文件会被一起读进来。gdf.columns打印出来的是属性字段常见的有name、adcode、city之类字段名因数据源而异必须先看清楚再写后续代码。gdf.crs如果打印出None说明 .prj 缺失或没被识别这时候要么补 .prj要么手动指定gdf.set_crs(EPSG:4326)。参数上read_file默认按文件编码读 dbf中文乱码时可以加encodingutf-8或encodinggbk试。3.2 城市名匹配先清洗再连接业务表里的城市名往往带“市”“地区”“自治州”后缀还可能有多余空格。直接做字符串相等匹配匹配率会很难看。稳妥做法是先做一轮标准化import pandas as pd # 假设业务表 biz 有 city 列 biz pd.read_csv(./data/store.csv) def normalize_city(name): if pd.isna(name): return None s str(name).strip() # 去掉常见后缀统一成核心名 for suffix in [市, 地区, 自治州, 盟, 特别行政区]: if s.endswith(suffix): s s[: -len(suffix)] break return s biz[city_key] biz[city].apply(normalize_city) gdf[city_key] gdf[name].apply(normalize_city) # 先看匹配率再决定是否继续 matched biz[city_key].isin(gdf[city_key]).mean() print(f匹配率: {matched:.2%})逻辑说明normalize_city只去掉一个后缀避免把“XX市市”这种脏数据越洗越乱。先算匹配率是关键一步匹配率低说明口径或命名规则有问题这时候应该回去核对数据源而不是继续往下做空间连接。参数上后缀列表要按你实际数据里出现的类型补全比如有些数据源用“自治县”那就得加进去。这一步做完把没匹配上的城市名单独导出来人工看一眼往往能发现是简称、别名或者历史名称的问题。3.3 空间连接把点落到面上如果业务数据带经纬度可以直接做空间连接比按名字匹配更可靠from shapely.geometry import Point # 业务表有 lng、lat 两列 biz[geometry] biz.apply(lambda r: Point(r[lng], r[lat]), axis1) biz_gdf gpd.GeoDataFrame(biz, geometrygeometry, crsEPSG:4326) # 确保两边坐标系一致 if gdf.crs ! biz_gdf.crs: biz_gdf biz_gdf.to_crs(gdf.crs) # 空间连接点在面内 joined gpd.sjoin(biz_gdf, gdf[[name, geometry]], howleft, predicatewithin) print(joined[name].isna().sum(), 个点未落入任何城市)逻辑说明predicatewithin表示点落在面内部才算匹配边界上的点可能匹配不上这是正常现象。howleft保证业务表所有行都保留没匹配上的name为 NaN方便后续排查。参数上如果点位在边界附近频繁丢失可以改用predicateintersects但要注意相邻城市共享边界时可能产生重复匹配需要去重。坐标系不一致时先to_crs对齐这一步不做空间连接结果会整体错位。4. 市级 shp 的常见避坑那些让你加班到深夜的细节4.1 现象地图整体偏移几百米点位全跑到海里原因源 shp 是 CGCS2000业务点位是 WGS84两者没对齐就直接叠加。解决统一用to_crs转到同一坐标系再操作展示层再转 Web 墨卡托。别在源文件上反复改保留一份原始底稿。4.2 现象城市名匹配率只有六成大量“XX市”对不上原因口径不一致业务表用的是地级市shp 用的是地级行政区自治州和地区被排除在外。解决换用地级行政区口径的 shp或者在匹配前把业务表里的“地区”“自治州”也纳入标准化规则做一次映射表兜底。4.3 现象dbf 里的中文城市名全是乱码原因dbf 的字符编码和读取时指定的编码不一致常见是源文件用 GBK代码默认按 UTF-8 读。解决读取时显式指定encodinggbk或者用 .cpg 文件确认编码。乱码不影响几何但会让所有按名字的匹配失效。4.4 现象空间连接后一个城市出现多条记录原因用了intersects且点位落在共享边界上或者 shp 本身存在重叠面。解决连接后按业务主键去重保留第一条同时检查 shp 是否有几何重叠用gdf.overlaps排查异常面。4.5 现象shp 打开报错“无法读取几何”原因文件组不完整或者 .shp 在传输中损坏。解决重新打包完整文件组用gpd.read_file前先确认 .shp、.shx、.dbf 三者大小正常损坏的文件只能重新获取。5. 进阶把市级 shp 做成可复用的匹配底表做到这一步单次分析已经能跑通了。但如果每周都要处理新一批业务数据每次都重新读 shp、重新清洗城市名效率很低。我的习惯是把市级行政区域 shp 预处理成一张“城市名—行政代码—几何中心”的匹配底表存成 parquet 或 gpkg后续直接查表。具体做法读入 shp 后用gdf.geometry.representative_point()取每个面的内部代表点再提取x、y作为中心坐标和城市名、行政代码一起落表。这样既保留了面数据用于地图渲染又有一张轻量的点表用于快速匹配。验证方法也简单拿一批已知城市的经纬度做回归测试看匹配结果是否和人工判断一致匹配率稳定在九成五以上再投入使用。参数上代表点用representative_point而不是centroid因为后者可能落在凹多边形的外部尤其是形状不规则的城市。另外底表要记录数据来源和口径版本行政区划是会调整的隔一段时间要核对一次别拿几年前的底表套新数据。我自己就吃过这个亏一份旧底表用了大半年某次业务方反馈“这个城市怎么没了”一查才发现区划调整过白忙一晚上。希望帮到你。本文还有配套的精品资源点击获取