ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Shapefile文件家族完全解读:从长江经济带shp包看矢量数据读取与处理

Shapefile文件家族完全解读:从长江经济带shp包看矢量数据读取与处理 简介长江经济带地级市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文本软件识别不到坐标系或要求你手动定义.cpgdbf文本编码声明属性中文乱码.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-1QGIS里属性表就会显示“锟斤拷”。自己处理时可以用文本编辑器查看并手动修改.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, encodingutf-8) # 打印前面5行属性 print(gdf.head()) # 查看坐标系信息 print(坐标系, gdf.crs) # 查看总要素数和几何类型 print(要素数, len(gdf)) print(几何类型, gdf.geom_type.unique())参数说明read_file的第一个参数是路径路径里如果有中文建议在字符串前加r用原始路径避免转义问题。encoding参数控制dbf文本字段的解码方式如果实际文件是GBK这里要改成encodinggbk。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把每个多边形的顶点坐标导出成csvimport geopandas as gpd gdf gpd.read_file(长江经济带.shp, encodingutf-8) # 对每个要素导出其多边形外包矩形坐标左上、右下等 bbox_df gdf.bounds.copy() bbox_df[市名] gdf[市名].values # 假设属性表有市名字段 bbox_df.to_csv(boundingbox.txt, indexFalse, sep,) # 如果要导出完整顶点坐标则需要遍历多边形 with open(coords.txt, w, encodingutf-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直接输出CSVogr2ogr -f CSV coords.csv 长江经济带.shp -lco GEOMETRYAS_XYZ-lco GEOMETRYAS_XYZ会把几何坐标按点展开每行输出一个顶点并且带上属性表字段。这个命令在Windows下需要把GDAL的bin目录加进PATHMac上如果用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, encodingutf-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, ascendingFalse)[[市名, 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, encodingutf-8) # 如果要做省级汇总可以用 dissolve gdf_prov gdf.dissolve(by省, aggfuncsum) gdf_prov.to_file(province.shp, encodingutf-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(tolerance0.001, preserve_topologyTrue)参数说明tolerance的值越大越简化但不要大到把城市边界拉直preserve_topologyTrue会避免简化后出现多边形相交或自交。注意如果CRS是经纬度容差单位是度0.001度约110米如果是投影坐标容差单位是米。简化后在QGIS里看一遍再决定使用。另一个常见需求是把地级市面转成外边界线得到“只保留外边界线”的效果。用GeoPandas可以这样boundary_gdf gpd.GeoDataFrame( gdf.drop(columnsgeometry), geometrygdf.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, encodingutf-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资源也能用同样的流程走一遍。本文还有配套的精品资源点击获取
返回列表