资讯动态

2017县级行政区shp实战:空间连接、面积计算与避坑指南

发布时间:2026/10/27 4:30:07 来源:尧图企业网站定制
简介面向GIS从业者、地理数据分析人员及规划相关专业学生的县级行政边界矢量数据集提供2017年中国各县级行政区划的空间范围可用于人口统计、城市规划、环境保护与灾害管理等叠加分析场景帮助读者快速获得可直接加载的行政边界底图。压缩包共7个文件、约46.33MB以shp主文件承载几何图形dbf存放县名与代码等属性prj定义CGS_WGS_1984坐标系shx、sbn、sbx为索引文件以加速检索xml记录元数据配套结构完整、开箱即用。已有615人学习下载适合需要精细县级边界开展空间分析的中级用户参考使用。1. 拿到一份 2017 县级行政区 shp先想清楚它能干什么县级行政区划矢量数据是很多空间分析项目的底座人口栅格统计、POI 归属判定、行政区划面积核算、专题地图底图几乎都要先落到县级边界上。标题里这份 2017 年的县级行政区 shp本质是一套面要素矢量数据属性表里通常带省、市、县名称和行政区划代码几何是县级行政边界多边形。它解决的核心问题是给任意带经纬度的点、线、面快速找到它落在哪个县或者反过来按县聚合统计。适合做区域经济分析、公共服务设施覆盖评估、遥感影像分区统计的从业者也适合需要一份稳定历史年份边界做时间对比的团队。2017 这个年份很关键行政区划每年都有调整拿错年份做跨年对比结论会直接翻车。2. 把 shp 读进来之前坐标系、编码与字段三件事2.1 先判断这份数据是地理坐标还是投影坐标shp 文件本身不自带“这是哪种坐标系”的完整语义真正定义坐标系的是同目录下的 .prj 文件。县级行政区数据常见两种情况一种是 WGS84 地理坐标单位是度适合做定位和存储另一种是某种投影坐标单位是米适合算面积和距离。打开之前先看 .prj 里有没有 PROJCS 字样有就是投影坐标只有 GEOGCS 就是地理坐标。这一步不做后面算面积会得到以“平方度”为单位的荒唐结果。我一般用 Python 的 geopandas 先探一下不急着做任何计算import geopandas as gpd # 读取 shp注意 encoding 参数县级数据中文属性常见 GBK gdf gpd.read_file(county_2017.shp, encodinggbk) print(gdf.crs) # 看坐标系定义 print(gdf.columns.tolist()) # 看字段名 print(gdf.head(3)) # 看前几行属性 print(len(gdf)) # 要素数量县级数据一般两千上下逻辑说明encodinggbk是因为很多国内来源的 shp 属性表用 GBK 存中文直接默认 UTF-8 读会报 UnicodeDecodeError 或读出乱码。gdf.crs打印出来如果是EPSG:4326就是地理坐标如果是类似EPSG:4547这类就是投影坐标。要素数量可以用来做一次粗校验全国县级行政区在两千个左右如果读出来只有几百条多半是只给了某个省的子集或者读取时过滤掉了空几何。参数说明encoding不是万能药如果 GBK 读出来还是乱码可以试gb18030它兼容范围更广。gdf.columns里重点找县名、县代码、市名、省名四类字段字段名可能是拼音也可能是中文取决于数据生产方。2.2 字段里最值钱的是行政区划代码县级数据的属性表里行政区划代码常见字段名如 code、adcode、XZQHDM比县名可靠得多。县名会重名比如多个省都有同名县靠名称做关联迟早出问题行政区划代码是六位数字前两位省、中间两位市、后两位县天然带层级关系。做跨表关联、做省市县汇总都应该以代码为主键名称只用来展示。需要提醒的是2017 年的代码和现在的代码不完全一致这些年有撤县设区、合并、更名的调整。如果你的下游数据是近两年的直接按代码关联会有一部分对不上。常见做法是保留一份代码变更对照或者在做时间序列分析时明确声明“边界固定为 2017 年口径”避免把区划调整误读成真实的数量变化。2.3 几何有效性检查不能省县级边界数据在数字化过程中容易出现自相交、重复点、悬挂节点这类几何错误。这些错误在单纯画图时看不出来但一做空间叠加比如用县界去裁剪栅格、做相交分析就会报拓扑异常或者算出错误的面积。读进来之后先跑一次有效性检查# 检查无效几何validity 为 False 的需要修复 invalid gdf[~gdf.geometry.is_valid] print(无效几何数量:, len(invalid)) # 常见修复方式buffer(0) 对多数自相交有效 gdf[geometry] gdf.geometry.buffer(0) print(修复后无效数量:, len(gdf[~gdf.geometry.is_valid]))逻辑说明is_valid返回布尔序列取反就筛出有问题的要素。buffer(0)是业界常用的“零缓冲”修复手法对自相交多边形往往能重建出合法几何但它不是万能药遇到严重重叠可能改变形状修复后要抽查面积变化。参数上 buffer 的距离设 0 是关键设正数会把多边形撑大设负数会收缩都会引入偏差。3. 用县级 shp 做点归属与按县聚合的完整流程3.1 点数据落到县空间连接的正确姿势最常见的需求是手里有一批带经纬度的点门店、监测站、事件记录想知道每个点属于哪个县。做法是空间连接spatial join把点的几何和县的面做“点在面内”判断。这里有两个容易翻车的点一是坐标系必须一致点如果是 WGS84、县如果是投影坐标直接连接会全错二是边界上的点归属落在县界上的点可能同时命中两个县需要定规则。import geopandas as gpd from shapely.geometry import Point # 点数据假设是 WGS84 经纬度 points gpd.GeoDataFrame( {pid: [1, 2, 3]}, geometry[Point(116.4, 39.9), Point(121.5, 31.2), Point(113.3, 23.1)], crsEPSG:4326 ) # 统一到县数据的坐标系 county gpd.read_file(county_2017.shp, encodinggbk) points points.to_crs(county.crs) # 空间连接predicatewithin 表示点落在面内 joined gpd.sjoin(points, county, howleft, predicatewithin) print(joined[[pid, 县名字段, 县代码字段]])逻辑说明to_crs(county.crs)把点转到县数据的坐标系这是必须的一步不能省。predicatewithin表示点的几何完全落在面的内部边界上的点不算命中如果希望边界点也算可以改用intersects但那样一个点可能匹配多个县需要在结果里按规则去重。howleft保证没匹配上的点也保留方便排查是数据问题还是坐标问题。参数说明predicate的取值直接决定边界行为within严格、intersects宽松做统计时我一般用within再单独处理未匹配点避免重复计数。如果连接后大量点未匹配先查坐标系是否真的统一再查点的经纬度是否写反经度纬度顺序搞反是高频错误。3.2 按县聚合用 dissolve 还是 groupby如果需求是“每个县有多少个点”有两种思路。一种是在空间连接后按县代码 groupby 计数简单直接另一种是先把点聚合成面再和县做叠加适合点特别多、需要先降维的场景。绝大多数情况下第一种就够用# 按县代码统计点数dropna 去掉未匹配的点 count_by_county ( joined.dropna(subset[县代码字段]) .groupby(县代码字段) .size() .reset_index(namepoint_count) ) print(count_by_county.head())逻辑说明dropna去掉没匹配上县的点避免把空值当成一个“县”统计。size()统计每组行数reset_index(name...)把结果整理成两列。这一步之后如果要出图再把统计结果 merge 回县的 GeoDataFrame用 point_count 做分级设色。参数说明groupby 的键必须是代码字段而不是名称字段原因前面说过重名会导致不同县被合并。如果确实需要按名称展示在最后出图前再映射名称不要在聚合阶段用名称。3.3 面积计算先投影再算别在地理坐标上直接算县级面积核算是另一个高频需求。地理坐标单位度下直接调area得到的是平方度没有物理意义。正确做法是先投影到合适的等积或等距投影再算面积。全国范围常用 Albers 等积投影分省分析可以用对应的地方投影。# 投影到 Albers 等积投影后再算面积单位平方米 county_albers county.to_crs(projaea lat_125 lat_247 lat_00 lon_0105 datumWGS84 unitsm) county_albers[area_km2] county_albers.geometry.area / 1e6 print(county_albers[[县名字段, area_km2]].head())逻辑说明to_crs里的 proj 字符串定义了一个 Albers 等积圆锥投影lat_1、lat_2是标准纬线lon_0是中央经线这套参数在国内全国尺度分析里比较常见。面积除以 1e6 把平方米换成平方公里。参数说明标准纬线要根据分析范围调整全国用 25 和 47 是常见取值只分析南方某区域时把标准纬线收窄到该区域纬度带面积误差会更小。投影参数不是随便填的填错会让面积系统性偏大或偏小。4. 避坑与排查县级 shp 处理里最容易翻车的五件事4.1 中文属性读出来是乱码现象读进来的县名字段显示成一堆问号或方块。原因shp 的 .dbf 属性表编码和读取时指定的编码不一致国内数据常见 GBK工具默认按 UTF-8 解。解决读取时显式指定encodinggbk不行再试gb18030如果已经读进来可以用gdf[字段] gdf[字段].str.encode(latin1).str.decode(gbk)做一次补救但成功率看原始字节最好还是在读取阶段解决。4.2 空间连接后大量点未匹配现象几千个点连接完只剩几十个有县归属。原因九成是坐标系不一致点用经纬度、县用投影坐标或者反过来剩下一成是经纬度顺序写反。解决连接前打印两边crs对比用to_crs统一检查点的坐标范围经度应在 -180 到 180、纬度在 -90 到 90如果出现 3000 多这种值基本可以确定是投影坐标被当成了经纬度。4.3 面积算出来大得离谱或小得离谱现象某个县面积算出几万平方公里明显不对。原因在地理坐标上直接算面积或者投影参数选错。解决确认crs是投影坐标再算面积投影的中央经线和标准纬线要覆盖分析区域算完抽查几个已知面积的县做对照偏差超过百分之几就要回头查投影参数。4.4 边界上的点被重复统计现象按县统计点数总数比原始点多。原因用了intersects做空间连接落在县界上的点同时命中相邻两个县。解决改用within或者连接后按点 id 去重、保留一个归属如果业务上确实需要边界点归属唯一可以加一个“按面积最大县优先”或“按代码最小县优先”的规则。4.5 拿 2017 边界去对近年数据数量对不上现象按县汇总的结果和官方近年统计口径差一截。原因行政区划调整撤县设区、合并导致县的数量和边界都变了。解决明确分析口径要么统一用 2017 边界并声明要么找一份代码变更对照把新旧代码映射起来不要默认“县的数量应该一样”区划调整是常态不是异常。5. 让这份 2017 县级数据真正好用的三个进阶习惯5.1 建一份可复用的字段映射配置不同来源的县级 shp 字段名五花八门每次换数据都改代码很累。我的习惯是抽一个配置字典把“代码字段、名称字段、市级字段、省级字段”做成可配置项读取后统一重命名成标准列名。这样下游所有分析代码只认标准列名换数据源只改配置不改逻辑。配置里还可以加一个“代码字段长度校验”六位是县、九位是乡镇长度不对直接报错比跑到一半才发现问题强。5.2 用空间索引加速大批量点连接点数量上万之后逐点判断“在哪个县”会明显变慢。geopandas 的sjoin底层已经用了空间索引但如果你自己写循环做geometry.contains性能会差一个数量级。大批量场景下先给县数据建spatial_index或者直接用sjoin不要手写双重循环。另一个技巧是先把点按经纬度做粗筛比如按县的包围盒先过滤再做精确判断能进一步降耗时。5.3 输出前做一次自检清单每次产出结果前我会固定跑几个检查要素数量是否在合理范围、代码字段是否有重复、面积字段是否有负值或零值、空间连接未匹配率是否超过阈值、投影是否统一。这几项里任何一项异常都先停下来查不要带着问题往下走。血泪经验是很多“结论奇怪”的分析根子都在数据读入阶段的一个编码或坐标系错误早查一分钟省下后面几小时的返工。检查项合理预期异常时先查要素数量两千上下全国口径是否只给了子集、是否过滤了空几何代码字段唯一性无重复是否混入了市级或省级记录面积字段均为正值投影参数、几何有效性空间连接未匹配率低于百分之几坐标系、经纬度顺序坐标系全流程统一每一步 to_crs 是否漏做这份 2017 县级行政区 shp 的价值不在于“新”而在于“稳”——年份固定口径清晰适合做需要可复现的历史对比。把它读对、连对、算对后面所有区域分析才有可信的地基。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑