☰
2017县级行政区shp文件:GIS空间分析与专题图制作实战指南
2026/10/20 6:10:09 网站建设 项目流程

简介:这份资源是2017年中国县级行政区划的矢量边界数据集,基于1:100万基础地理数据库整理,面向从事GIS分析、城市规划、人口统计与灾害管理等工作的技术人员及地理信息相关专业师生。压缩包共7个文件,约46.33MB,以SHP格式为核心,配套DBF属性表、PRJ坐标系定义、SHX/SBN/SBX索引及XML元数据,分别承载几何边界、县名与代码等属性、CGS_WGS_1984坐标信息以及加速检索的索引结构,便于在ArcGIS、QGIS等软件中直接加载与叠加分析。目前已有614人学习下载。借助这套精细的县级行政边界,读者可将其与人口密度、地形地貌、气候等数据叠加,开展空间统计、区域规划与专题制图,快速搭建全国尺度的分析底图,减少自行数字化边界的时间成本。

1. 1100万基础地理数据库:2017县级行政区shp文件能解决哪些实际问题

如果你做过全国尺度的专题图、空间统计或者行政区划匹配,大概率遇到过这种场景:手头有一份业务数据,字段里只有“XX县”“XX区”这样的名称,想把它落到地图上,却发现找不到一套干净、完整、带标准编码的县级边界。网上搜到的shp要么缺几个省,要么属性表里只有NAME没有adcode,要么坐标系是五花八门的投影坐标,合并起来对不上。这套1100万基础地理数据库的2017县级行政区shp文件,就是冲着这类需求来的——它提供的是全国县级行政单元的矢量边界,比例尺1:1100万,属性结构相对规整,适合做全国尺度的可视化底图、空间连接和区域汇总。适合谁用?做GIS分析、数据可视化、城乡规划、物流分区、市场覆盖分析的从业者,以及需要一份可靠县级底图做二次开发的人。它不是那种高精度大比例尺数据,但在全国宏观分析这个层级上,够用且省事。

2. 先搞清楚这份shp里到底装了什么:字段、坐标系与几何类型

拿到一份shp,最忌讳的就是直接往GIS软件里一拖然后开始画图。我见过太多人因为没看坐标系,把数据叠到在线底图上发现偏了几百公里,然后开始怀疑人生。这一章先把这份数据的“底细”摸清楚,后面用起来才不慌。

2.1 属性表字段解读:NAME、adcode与层级关系

县级行政区shp的属性表通常包含几个核心字段:行政区名称(NAME)、行政区代码(adcode)、上级行政区名称或代码、几何类型等。2017年的县级区划代码是6位数字,前两位是省级,中间两位是市级,后两位是县级。这个编码规则很重要,因为它是你做数据关联时最稳定的键——名称会变,编码不会。

常见做法是先用QGIS或ArcGIS打开属性表,看字段名和字段类型。如果adcode是字符串类型,关联时要注意别被自动转成数字丢了前导零。我一般会先跑一遍字段统计,确认县级单元数量在2800左右(2017年前后全国县级区划大致在这个量级),如果差太多,说明数据可能被裁剪过或者有缺失。

import geopandas as gpd # 读取shp文件,注意指定编码,中文环境常用gbk或utf-8 gdf = gpd.read_file("county_2017.shp", encoding="utf-8") # 查看字段名、类型和前5行 print(gdf.dtypes) print(gdf.head()) # 检查县级单元数量 print("县级单元数量:", len(gdf)) # 检查adcode是否有重复 if "adcode" in gdf.columns: dup = gdf[gdf.duplicated("adcode", keep=False)] print("重复编码数量:", len(dup))

这段代码的逻辑很直接:先读进来,看字段类型和数量,再查编码重复。参数上,encoding要根据实际文件调整,如果读出来是乱码就换gbk试试。geopandas底层用的是fiona,对中文编码的支持有时候看运气,遇到报错可以先用QGIS转成utf-8再读。

2.2 坐标系与投影:为什么你叠图会偏

1:1100万基础地理数据库的县级shp,常见坐标系有两种可能:一种是地理坐标系WGS84(EPSG:4326),单位是度;另一种是投影坐标系,比如Albers等面积投影或Lambert投影,单位是米。如果你拿到的是WGS84,直接叠到Web地图上问题不大;如果是投影坐标,就必须先做坐标转换,否则和在线底图对不上。

判断方法很简单:在QGIS里看图层属性,或者用geopandas读crs。

print(gdf.crs)

如果输出是EPSG:4326,那就是经纬度;如果是其他代码,比如EPSG:3857或者自定义投影,就要注意了。做全国尺度分析时,我一般会统一转成Albers等面积投影,因为算面积、做缓冲区时,经纬度坐标下的距离和面积是不准确的。

# 转为Albers等面积投影,适合全国尺度 gdf_albers = gdf.to_crs("EPSG:6370") # 中国Albers投影常用参数

这里EPSG:6370是一个常见的中国Albers投影代码,但不同软件里参数可能略有差异。如果你只是做展示,不涉及面积计算,保持WGS84也够用。关键是:叠图前先确认坐标系一致,这是血泪经验。

2.3 几何类型与数据完整性检查

县级行政区shp的几何类型一般是Polygon或MultiPolygon。MultiPolygon常见于有岛屿或飞地的县,比如沿海县市。检查几何有效性是必要步骤,因为有些数据来源的边界可能存在自相交、空几何等问题,直接做空间分析会报错。

# 检查几何有效性 invalid = gdf[~gdf.is_valid] print("无效几何数量:", len(invalid)) # 修复无效几何 gdf["geometry"] = gdf["geometry"].buffer(0)

buffer(0)是一个老技巧,能把大部分自相交问题修掉,但不是万能的。如果无效几何很多,建议用make_valid或者回到QGIS里手动处理。另外,检查一下有没有空几何:

empty = gdf[gdf.is_empty] print("空几何数量:", len(empty))

这两步做完,你对这份数据的质量就有了基本判断。如果县级单元数量对得上、坐标系明确、几何基本有效,那这份数据就可以进入下一步使用了。

3. 把shp用起来:从数据关联到全国专题图的操作流程

数据检查完,接下来就是实际使用。这一章围绕两个最典型的场景展开:一是把业务数据通过行政区名称或编码关联到shp上,二是做一张全国县级专题图。中间会涉及空间连接、属性连接、可视化参数设置,以及导出时的注意事项。

3.1 属性关联:用adcode把业务数据挂到边界上

假设你有一份CSV,字段是“区县名称”和“指标值”,想把它变成地图上的颜色深浅。最稳的方式是用adcode关联,而不是用名称。名称关联的翻车率很高,比如“XX市”可能对应多个县级单元,或者名称里有空格、全半角差异。

import pandas as pd # 读取业务数据 df = pd.read_csv("biz_data.csv", dtype={"adcode": str}) # 确保adcode格式一致,补零到6位 df["adcode"] = df["adcode"].str.zfill(6) gdf["adcode"] = gdf["adcode"].astype(str).str.zfill(6) # 关联 merged = gdf.merge(df, on="adcode", how="left") # 检查关联率 matched = merged["指标值"].notna().sum() print(f"关联成功: {matched}/{len(merged)}")

这段代码的关键在dtype={"adcode": str}和zfill(6)。很多CSV里的编码会被自动读成数字,前导零丢失,导致关联失败。关联率如果低于90%,就要检查两边的编码格式是否一致,或者是否存在区划调整导致的编码变更。2017年的数据和现在的区划可能有出入,比如某些县改区、合并,这时候需要一份区划变更对照表来做映射。

3.2 空间连接:把点数据汇总到县级单元

另一个常见需求是:你有一堆带经纬度的点,想统计每个县里有多少个点。这时候用空间连接(spatial join)比属性关联更直接。

from shapely.geometry import Point # 假设points是带经纬度的DataFrame points_gdf = gpd.GeoDataFrame( points, geometry=[Point(xy) for xy in zip(points["lon"], points["lat"])], crs="EPSG:4326" ) # 确保坐标系一致 points_gdf = points_gdf.to_crs(gdf.crs) # 空间连接 joined = gpd.sjoin(points_gdf, gdf[["adcode", "geometry"]], how="left", predicate="within") # 按县统计 count_by_county = joined.groupby("adcode").size().reset_index(name="point_count")

predicate="within"表示点落在县边界内。如果点正好在边界上,可能会被算到相邻县,这是空间连接的常见边界问题。解决办法是用representative_point或者加一个很小的buffer。统计完之后再和gdf关联,就能得到每个县的点数量。

3.3 全国专题图出图:配色、标注与导出参数

出图这一步,QGIS比代码更直观,但如果你要批量出图或者做自动化,matplotlib加geopandas也能搞定。关键是几个参数:配色方案、缺失值处理、图例和标注。

import matplotlib.pyplot as plt fig, ax = plt.subplots(1, 1, figsize=(16, 12)) # 绘制县级边界,按指标值填色 merged.plot( column="指标值", ax=ax, legend=True, cmap="OrRd", missing_kwds={"color": "lightgrey", "label": "无数据"}, edgecolor="white", linewidth=0.1 ) ax.set_title("2017年全国县级指标分布", fontsize=16) ax.axis("off") plt.savefig("county_map.png", dpi=300, bbox_inches="tight")

cmap选OrRd是因为它在打印和屏幕上都有不错的辨识度。missing_kwds把无数据区域标成浅灰,避免误导读者。linewidth设0.1是为了让县级边界不至于太粗,全国2800多个县,线太粗会糊成一片。导出dpi设300,够用。如果要做交互式地图,可以导出GeoJSON再用Leaflet或Mapbox渲染,但要注意文件大小,全国县级边界GeoJSON大概几十MB,简化几何后能压到几MB。

4. 避坑与排查:县级shp使用中最容易翻车的五个地方

这一章是我自己踩过的坑,也是周围同行问得最多的问题。每条按“现象→原因→解决”写,不绕弯子。

4.1 叠图偏移几百米到几公里

现象:把shp叠到在线底图上,边界整体偏移,偏移量从几百米到几公里不等。原因:坐标系不一致。在线底图通常是Web Mercator(EPSG:3857),而shp可能是WGS84或者某种投影坐标。解决:在QGIS里用“重新投影图层”功能,或者在代码里to_crs("EPSG:3857")。注意,WGS84到Web Mercator的转换是数学公式,不涉及基准面转换,偏移不会太大;但如果是北京54或西安80,就需要做基准面转换,参数不对会偏得更离谱。

4.2 关联后大量县匹配不上

现象:用名称关联业务数据,匹配率只有六七成。原因:名称不一致,比如“XX县”和“XX市”混用、全半角括号、空格、少数民族地区名称的音译差异。解决:优先用adcode关联;如果只有名称,先做标准化——去空格、统一括号、建立别名表。我一般会先跑一遍名称比对,把匹配不上的列出来,人工确认几个典型case,再写映射规则。

4.3 面积计算出来是负数或者大得离谱

现象:用shp算面积,结果和实际差几个数量级。原因:在经纬度坐标系下直接算面积,单位是“平方度”,没有物理意义。解决:先转成等面积投影,比如Albers,再算面积。代码里gdf.to_crs("EPSG:6370")之后,area属性的单位就是平方米。

4.4 导出GeoJSON后中文乱码

现象:导出GeoJSON用浏览器打开,中文名称显示为乱码。原因:编码不一致,shp可能是gbk,导出时没指定utf-8。解决:在geopandas里to_file时加encoding="utf-8",或者先用QGIS导出并指定编码。另外,GeoJSON标准要求utf-8,所以这一步不能省。

4.5 数据版本与区划变更对不上

现象:2017年的县级边界和2023年的业务数据关联,发现少了几个县或者多了几个。原因:区划调整,比如某县改区、某地级市新设区。解决:找一份区划变更对照表,做编码映射。如果没有对照表,至少把匹配不上的单元列出来,手动确认归属。常见做法是保留两套编码,一套用于历史数据,一套用于当前数据,分析时注明口径。

5. 进阶用法:用这份shp做区域汇总与自动化出图

基础操作跑通之后,可以往自动化方向走。我自己的习惯是把县级shp作为底图库,配合一份区划对照表,封装成一个函数,输入业务数据和指标名,直接输出专题图和汇总表。这样每次有新数据,不用重复折腾坐标系和关联。

5.1 按省/市汇总:从县级到上级行政区的聚合

县级数据汇总到市级或省级,有两种方式:一是按adcode前缀分组,前两位是省,前四位是市;二是用dissolve按上级字段合并几何。

# 按省级汇总 gdf["province_code"] = gdf["adcode"].str[:2] province_gdf = gdf.dissolve(by="province_code", aggfunc="sum") # 按市级汇总 gdf["city_code"] = gdf["adcode"].str[:4] city_gdf = gdf.dissolve(by="city_code", aggfunc="sum")

dissolve的aggfunc参数决定数值字段怎么聚合,sum适合总量指标,mean适合比率指标。几何上,dissolve会把同一个市的所有县合并成一个多边形,边界自动融合。这一步在QGIS里对应“融合”工具,但代码里做更方便批量处理。

5.2 批量出图:循环生成每个省的县级专题图

如果你需要给每个省单独出一张图,可以用循环加空间筛选。

provinces = gdf["province_code"].unique() for prov in provinces: subset = merged[merged["province_code"] == prov] fig, ax = plt.subplots(figsize=(10, 8)) subset.plot(column="指标值", cmap="OrRd", legend=True, ax=ax, missing_kwds={"color": "lightgrey"}) ax.set_title(f"省份代码 {prov} 县级指标分布") ax.axis("off") plt.savefig(f"province_{prov}.png", dpi=200, bbox_inches="tight") plt.close()

这个循环的逻辑是:按省代码筛选,画图,保存,关闭。plt.close()很重要,不然循环多了内存会爆。dpi设200是因为单省图不需要300那么高,文件小一点方便传输。

5.3 几何简化:让GeoJSON小到能塞进网页

全国县级边界原始GeoJSON可能几十MB,网页加载慢。用simplify做几何简化,能压到几MB。

gdf_simplified = gdf.copy() gdf_simplified["geometry"] = gdf_simplified["geometry"].simplify(0.01) gdf_simplified.to_file("county_simplified.geojson", driver="GeoJSON", encoding="utf-8")

simplify的参数0.01是容差,单位跟坐标系一致。如果是WGS84,0.01度大约是1公里,全国尺度下肉眼几乎看不出差别,但文件能小很多。如果做省级或市级展示,容差可以再小一点,比如0.001。注意,简化后几何可能会有轻微变形,做精确面积计算时不要用简化后的数据。

从那以后我每次拿到新的shp,都强制走一遍“看crs→查字段→验几何→试关联”的流程,不再直接拖进软件就画图。这套习惯帮我省了不少返工时间。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询