简介:长江经济带地级市shp图.zip是一份覆盖长江经济带范围内全部地级市行政边界的Shapefile地理数据包,面向GIS使用者、城市规划与区域研究人员,可直接用于地图绘制、空间分析和基础底图搭建,省去自行矢量化的时间。压缩包共9个文件,涵盖核心的.shp几何数据、.dbf属性表、.prj投影定义、.shx索引文件,以及辅助的.sbn/.sbx空间索引和.xml元数据,是一套结构完整的地理空间矢量数据集,可无缝加载至ArcGIS、QGIS等主流GIS平台使用。整个资源包仅1.92MB,轻量紧凑,但覆盖内容完整,配套的字符编码与投影信息能够保证数据处理准确性。已有1010人浏览学习,被较多使用者验证。获取后可获得可直接使用的地级市边界数据,适合作为长江经济带区域发展研究、环境评估与交通规划的底层空间资料。
1. 一个能直接打开的长江经济带边界包,但先别急着拖进ArcGIS
拿到“长江经济带地级市shp图.zip”这样一个压缩包,解开后里面躺着十几个同名不同后缀的文件,新手第一反应通常是只把末尾是.shp的文件拖进ArcGIS或QGIS,结果弹出一个“无法打开”的报错。这不是数据坏了,而是Shapefile本身就是一大家子文件:主文件存几何、dbf存属性表、shx是定位索引,再加上prj、cpg、sbn等等,任何一个成员缺席都会影响读取。这篇东西会把包里每个文件干什么、怎么读、怎么转、常见的坑在哪里讲完整,适合刚接触shp的规划和分析人员,也适合那些手头有一堆边界数据但一直用得很粗糙的GIS老手。
2. Shapefile不是“一个文件”:把包里的每个后缀名都看懂
一开始先立住概念:Shapefile实际上.shp主文件、.shx索引、.dbf属性表这三个是基础,缺一个读不到数据;其他则是辅助信息。下面详细讲。
2.1 为什么必须三件套配齐:.shp、.shx、.dbf的分工
.shp是以一系列二进制记录存储几何位置的,第几条记录对应哪个多边形,并不带任何业务字段。.shx是一个“明细表”,记录着每条几何记录在.shp文件中的偏移量和长度,相当于书目录。.dbf是关系表,每一行对应.shp里的一个要素,存着市名、省份、面积、代码之类的属性,用dBASE格式存储。GIS软件读取边界时,先读.shx从.shp中定位几何,再把.dbf里的属性按行号拼回去。因此丢失.shx时很多软件会尝试扫描重建,但.dbf丢了就只剩一堆光秃秃的多边形;缺.shp则连图形都没有。
2.2 压缩包里10个文件逐个拆解
| 文件名后缀 | 作用 | 丢失/异常后的表现 |
|---|---|---|
| .shp | 几何坐标主体 | 无图形或无法打开 |
| .shx | 几何索引 | 有些软件自动重建,老软件直接报错 |
| .dbf | 属性数据 | 属性表打不开或要素无属性 |
| .prj | 坐标系描述(WKT文本) | 软件识别不到坐标系,或要求你手动定义 |
| .cpg | dbf文本编码声明 | 属性中文乱码 |
| .sbn/.sbx | 空间索引对 | 部分软件重新生成;缺少时查询变慢 |
| .shp.xml | 元数据 | 一般无感知 |
| .sr.lock | 编辑锁文件 | 无影响,可删除 |
这个压缩包里还出现了“长江经济带.shp.FHUR2IBAJIAEQVG.6160.10748.sr.lock”。它看起来像数据文件,其实是ArcGIS或QGIS在编辑会话中生成的锁文件,记录某个进程正在占用.shp。文件命名在原来的shp名后面拼了一段随机字符再加.sr.lock。正常使用中用不到它,而且因为压缩包是静态的,里面的锁文件往往是无意间打包进去的,完全可以删掉。如果解压后直接放到共享目录且有锁文件存在,反而会让某些GIS服务误判文件被占用。建议先删掉所有*.sr.lock再加载。
再来是.prj。它是一个纯文本文件,内容是一段基于WKT的坐标系统描述,比如GEOGCS["GCS_WGS_1984", DATUM[...], PRIMEM[...], UNIT[...]]这种结构。打开它就能确认这个shp是经纬度还是已经做过投影,比如是否是CGCS2000的3度分带。数据加载后如果地图上位置不对,先看.prj存在不存在,再看它描述的坐标系和当前工程是否一致。
.cpg文件的作用常被忽略。它只有一行,记录.dbf里文本字段的字符集,常见内容为UTF-8或GBK。中文地级市名称最容易在这里出问题:如果.cpg丢失或写成ISO-8859-1,QGIS里属性表就会显示“锟斤拷”。自己处理时,可以用文本编辑器查看并手动修改.cpg里的编码名,然后重新加载数据。
还有.sbn和.sbx是一对空间索引,ArcGIS在加速空间查询时会用。如果压缩包里没有,也没关系,GeoPandas和QGIS都不依赖它,ArcGIS打开后会自动重建。
2.3 先检查再打开:解压后的第一件事
把zip解压后,不要急着双击.shp。我一般会先依次做三个检查:挨个看一遍文件后缀,确认.shp、.dbf、.shx三个都在;再用文本编辑器打开.cpg,看编码是不是UTF-8;然后打开.prj,确认坐标系统。如果.cpg不存在,后面用Python读取时我会显式指定encoding,避免乱码。如果.prj不存在,那就要在GIS软件里手动指定坐标系,千万别拿WGS84强行套,否则面积和位置都会偏。
后面第三、四章就是怎么读、怎么处理的实际操作。
3. 用Python和命令行把shp读进来、看到边界
做地理分析绕不开读取。GeoPandas是Python生态里最顺手的矢量读库,pyshp则适合轻量级或自定义解析。这里用GeoPandas示例,因为代码最接近日常分析习惯。
3.1 安装与读取
先确认环境里已装geopandas及其依赖。常规安装:
pip install geopandas读取本地shp文件:
import geopandas as gpd # 读取长江经济带地级市边界 gdf = gpd.read_file("长江经济带.shp", encoding="utf-8") # 打印前面5行属性 print(gdf.head()) # 查看坐标系信息 print("坐标系:", gdf.crs) # 查看总要素数和几何类型 print("要素数:", len(gdf)) print("几何类型:", gdf.geom_type.unique())参数说明:read_file的第一个参数是路径,路径里如果有中文,建议在字符串前加r用原始路径,避免转义问题。encoding参数控制dbf文本字段的解码方式,如果实际文件是GBK,这里要改成encoding="gbk"。gdf.crs如果显示None,说明缺少.prj文件,数据加载时不会自动带坐标系,后续做投影转换前必须先手动赋值。geom_type会输出Point、Polygon、MultiPolygon等,地级市边界通常是MultiPolygon,因为一些市会有飞地和岛。
如果你更想快速看图,直接用QGIS拖进去最稳;但想批量做面积、合并、筛选,Python更顺手。
3.2 命令行ogrinfo和ogr2ogr快速探测与转换
GDAL自带的ogrinfo不依赖图形界面,几毫秒内就能摸清数据结构。在终端执行:
ogrinfo -so -al 长江经济带.shp-so表示只输出摘要,不逐要素打印;-al列出所有图层;最后的参数是文件路径。输出结果会显示要素数量、坐标范围、几何类型、属性字段清单和字段类型。例如:
INFO: Open of `长江经济带.shp' using driver `ESRI Shapefile' successful. Layer name: 长江经济带 Geometry: Polygon Feature Count: 45 Extent: (98.5, 22.3) - (122.0, 35.5)看到坐标范围在98~122度之间,基本能判断这是经纬度数据;如果看到“纬度”的y值出现负值,那要检查投影方向。Feature Count是地级市数量,一个市一行;如果比实际地级市数量少,可能需要检查是否缺漏,但边界数据也是分层的,有些只是把省界和地市界放一起。
3.3 把shp转成txt坐标文本:两个常用办法
热搜里不少人搜“shp转txt”,实际是要把边界坐标导出成x/y列表,用于程序画图或读取。最简单的是用geopandas把每个多边形的顶点坐标导出成csv:
import geopandas as gpd gdf = gpd.read_file("长江经济带.shp", encoding="utf-8") # 对每个要素,导出其多边形外包矩形坐标(左上、右下等) bbox_df = gdf.bounds.copy() bbox_df["市名"] = gdf["市名"].values # 假设属性表有市名字段 bbox_df.to_csv("boundingbox.txt", index=False, sep=",") # 如果要导出完整顶点坐标,则需要遍历多边形 with open("coords.txt", "w", encoding="utf-8") as f: for idx, row in gdf.iterrows(): geom = row.geometry # 取多边形每个环的所有顶点 if geom.geom_type == "Polygon": coords = list(geom.exterior.coords) elif geom.geom_type == "MultiPolygon": coords = [] for poly in geom.geoms: coords.extend(list(poly.exterior.coords)) else: coords = [] for x, y in coords: f.write(f"{row['市名']},{x},{y}\n")这里逐环导出:MultiPolygon处理更复杂,代码用poly.exterior.coords取外环,如果有些地理区域内部有洞(比如飞地之间的水域),还需同时取interior ring,但一般边界图用外环就够了。bounds得到每行的minx、miny、maxx、maxy,是最常见的外包框文本。
另一个办法是使用GDAL的ogr2ogr,直接输出CSV:
ogr2ogr -f CSV coords.csv 长江经济带.shp -lco GEOMETRY=AS_XYZ-lco GEOMETRY=AS_XYZ会把几何坐标按点展开,每行输出一个顶点,并且带上属性表字段。这个命令在Windows下需要把GDAL的bin目录加进PATH,Mac上如果用Homebrew装了gdal,直接可用。注意输出的字段名可能带序号,尤其在dbf里有重名段时。
3.4 编码错误时的兜底方案
如果读文件时指定utf-8报错,比如UnicodeDecodeError,先用文本编辑器打开.dbf?——其实.dbf是二进制,编辑器看不了。正确做法是先用ogrinfo打印字段,再用gpd.read_file的encoding参数逐个试:gbk、gb18030、utf-8。也可以直接看.cpg内容,读到的就是正确编码。如果.cpg是GBK但属性里混有特殊符号,用gb18030比gbk兼容性更好。
读进来之后,下一步就是处理,比如计算面积、按城市筛选、转Web图层。
4. 地级市边界怎么处理:投影转换、面积计算与出图前准备
拿到边界数据后,工作还没结束。规划人员和数据工程师常要做三件事:算各省份或各市面积、按特定城市筛选、输出成GeoJSON或GeoPackage。这一章把这些操作串起来,并解释投影为什么影响结果。
4.1 投影常识:不要直接用经纬度算面积
数据若为WGS84经纬度坐标,单位是度;在度单位下用geometry.area得到的数不是平方米,而是“平方度”,量级没有直观意义,也不能直接换算。正确做法是先投影到一个合适的平面坐标系,再算面积。长江经济带从上海延伸到四川,横跨约25个经度。若用高斯-克吕格3度分带,跨带太多,边缘变化严重。更常见是用Albers等积圆锥投影(Krasovsky_Albers或CGCS2000 Albers),它专门用来平衡中国的全国范围面积计算,或者用World Mercator也不算可行。所以这里推荐通用办法:用EPSG:102025这类Albers投影,或者手写投影参数;如果只需比较城市间规模,用EPSG:3857的墨卡托也可以,但面积会随纬度偏高。
在geopandas里转换投影:
import geopandas as gpd gdf = gpd.read_file("长江经济带.shp", encoding="utf-8") # 把坐标系从经纬度转换到Albers等积投影 albers = gdf.to_crs("EPSG:102025") # 计算面积,单位变为平方米 albers["area_km2"] = albers.geometry.area / 1e6 albers["area_km2"] = albers["area_km2"].round(2) # 按面积降序排 print(albers.sort_values("area_km2", ascending=False)[["市名", "area_km2"]].head(10))注意:EPSG:102025的适用范围偏整个中国,如果你的数据只是局部,用它可能不精确,但作为入门示例没问题。如果不确定原始坐标系,先用gdf.crs看,若为EPSG:4326,就按上面转;若prj显示的是北京54或西安80,转EPSG:102025前需要先转成CGCS2000,再转目标投影,中间可以这样写:
gdf_84 = gdf.to_crs("EPSG:4326") albers = gdf_84.to_crs("EPSG:102025")这里分两步,是因为很多自定义投影没有直接转换关系,需要先统一到基准地理坐标。
4.2 按字段筛选与按省合并
属性表里通常有省份、地市名称字段,如果字段名是中文,需注意读取后的列名。GeoPandas可以直接按列筛选:
# 假设字段名为 "省" hubei = gdf[gdf["省"] == "湖北省"] # 导出子集 hubei.to_file("hubei.shp", encoding="utf-8") # 如果要做省级汇总,可以用 dissolve gdf_prov = gdf.dissolve(by="省", aggfunc="sum") gdf_prov.to_file("province.shp", encoding="utf-8")dissolve会把一个省的所有地级市边界合并成省级边界,参数by指定分组合并列;aggfunc指定如何合并属性统计值,字符串字段默认取第一个值,数值字段可以传入字典。比如aggfunc={"总人口": "sum"},省边界就能自动带上人口合计数。在执行dissolve前最好确认字段名没有空格,dbf字段名最长10个字符,很多中文软件会截断,所以读取后如果列名和预期不符,先用gdf.columns.tolist()查看。
4.3 简化与悬空节点:出图前处理
在QGIS里直接加载后,如果显示很慢或者出图线条过于平滑,可以先用shapely做简化。这一般放在投影转换之后,因为原始边界有很多碎点,影响绘制性能:
from shapely.geometry import shape # 简化几何,容差设为0.001度(约100米级),保持拓扑不被破坏 gdf["geometry"] = gdf.geometry.simplify(tolerance=0.001, preserve_topology=True)参数说明:tolerance的值越大越简化,但不要大到把城市边界拉直;preserve_topology=True会避免简化后出现多边形相交或自交。注意如果CRS是经纬度,容差单位是度,0.001度约110米;如果是投影坐标,容差单位是米。简化后在QGIS里看一遍,再决定使用。
另一个常见需求是把地级市面转成外边界线,得到“只保留外边界线”的效果。用GeoPandas可以这样:
boundary_gdf = gpd.GeoDataFrame( gdf.drop(columns="geometry"), geometry=gdf.boundary )gdf.boundary直接生成每条多边形边界的线要素,MultiPolygon会忽略各个子多边形之间的公共边,只保留整体外边界。这在热词里有人搜“shp有没有办法只保留外边界线”,实际就是这行代码。转出来的线图可用于简化地图底图。
4.4 输出为GeoJSON或GeoPackage
现在Web地图应用比较流行,把shp转GeoJSON很简单:
ogr2ogr -f GeoJSON 长江经济带.geojson 长江经济带.shp如果是给前端用,并且数据量大于几MB,建议在转出时指定-t_srs EPSG:4326,避免投影坐标导致前端引擎报错。转成GeoPackage更适合移动端和数据库存取:
ogr2ogr -f GPKG 长江经济带.gpkg 长江经济带.shpGeoPackage是一个单文件SQLite容器,可以把多个图层和样式一起塞进去,比散落一堆shp姊妹文件好管理得多。在ArcGIS Pro中则是直接“导入要素类”到地理数据库,转成gdb。注意这里有个热词“shp转gdb和gdb是一样的东西吗”,严格说不是:gdb是Esri的文件地理数据库,shp是开放交换格式,两者都能存几何和属性,但gdb支持拓扑、网络、注记等高级结构。如果你只是要换个容器,用GeoPackage就够了,不需要和gdb死磕。
4.5 数据缺失和字段缺失怎么办
打开后如果发现某些市没有属性数据,比如面积字段为空,可以用几何计算补上;如果缺字段,也可以在GeoPandas里新增列再导出。下面这个脚本给每个地级市打上面积等级:
import geopandas as gpd gdf = gpd.read_file("长江经济带.shp", encoding="utf-8") gdf_albers = gdf.to_crs("EPSG:102025") gdf_albers["area"] = gdf_albers.geometry.area / 1e6 def size_label(area): if area > 20000: return "large" elif area > 5000: return "medium" else: return "small" gdf_albers["等级"] = gdf_albers["area"].apply(size_label)此处的apply是pandas的逐行映射,注意函数不能调用gdf变量,否则闭包写复杂了容易错。字段长度限制在dbf格式是10个字符,中文一个字符在有些编码下算两个字节,所以如果输出字段名过长,导出时会被截断或报错,最好用英文短字段名。
到这一步,你的长江经济带边界数据已经能够正常读取、转换、按需导出,接下来进入排错环节。
5. 打开报错别急着删:文件锁、编码和中文字段排错技
最后这章收敛到实际使用中容易撞上的几个问题。很多初学的朋友解压后直接双击.shp,被系统提示“不是一个有效文件”。原因往往是文件家族不完整,或者被Windows资源管理器隐藏了扩展名。先说说常见报错对应的处理顺序。
第一个高频错误是The dbf file cannot be opened.或属性表空白。这通常不是dbf文件损坏,而是软件按错误编码读取。在QGIS中点开属性,选择合适的编码;ArcGIS中设置数据源编码;而用Python脚本读取时,像上面说的把encoding参数改成gbk/gb18030就能解决。另一个细节是压缩包解压时,Windows可能把.cpg文件漏掉或改名,这也会导致编码识别失败,所以解压后先检查文件列表。
第二个易踩的坑是.sr.lock锁文件。它出现在包里并不代表数据正在被编辑,只是当初打包时软件还开着、并且启用了编辑会话。把锁文件放在包里一起压缩,解压后会造成某些服务端GIS工具检测到锁,不敢对文件写入。遇到这种情况,直接删掉所有*.sr.lock再加载,不会有任何数据损失。如果你用的是共享目录且同事同时开着同路径下的文件,那就要先关掉那边的项目,而不是强行删除。
第三个问题是“文件路径中文+空格”导致读取异常。Shapefile本身对路径的兼容性不是很好,在Windows下给ArcGIS加载时,路径里有中文一般还行,但如果再叠加图层名称里的中文字段,偶尔就出怪问题。稳妥做法是先把整个文件夹整理成不带空格的英文路径,比如C:/gis/yzjj/shp。同时尽量避免把文件放在桌面上,因为user profile路径里经常有空格和特殊字符。
最后给一个自检脚本,用pyshp检查shp是否完整可读:
pip install pyshpimport shapefile try: reader = shapefile.Reader("长江经济带.shp") print("要素数:", len(reader)) print("边界范围:", reader.bbox) print("字段列表:", reader.fields) except Exception as e: print("读取失败:", e)如果pyshp能读出来,说明几何部分基本正常;如果这里正常但GeoPandas报错,多半是编码或投影问题,先用ogrinfo核对。最后一个小技巧:在ArcGIS里反复打开报错时,把该.shp复制到新建目录,并手动补齐.dbf、.shx、.prj、.cpg四个文件,然后重新加载,很多顽固问题其实是旧缓存。
这样一套下来,压缩包里那些看起来乱七八糟的后缀名就都成了可以把握的环节:哪些是必选、哪些是辅助、哪些可以删,什么时候该指定编码,什么时候必须转投影,都有了明确处理路径。下次再拿到别的shp资源,也能用同样的流程走一遍。
本文还有配套的精品资源,点击获取