ARTICLE DETAIL

资讯详情

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

Shapefile格式详解:南通乡镇街道shp数据处理与坐标转换实战

Shapefile格式详解:南通乡镇街道shp数据处理与坐标转换实战 简介面向 GIS 从业者、规划研究者与高校师生提供南通市下辖各区县、乡镇和街道的行政界线 Shapefile 数据可快速用于地图制图、空间统计分析及论文专题插图。压缩包共 21 个文件由三组要素构成市级、区县级与乡镇街道级 shp 分别记录不同层级的几何边界配套 dbf 存有行政名称等属性信息prj 标明坐标系另有 sbn、sbx 空间索引与 xml 元数据文件ArcGIS、QGIS 等软件解压后均可直接读取。整体体积仅 180KB轻量小巧不必在各类数据平台间反复搜索甄别。目前已有 399 人浏览学习资源内按不同行政层级分文件组织使用者可根据制图比例尺灵活选取对应图层直接叠加标注或做专题配色若需与其他坐标系资料叠加请先借助 prj 文件完成投影转换。适合需要快速获取南通市基层政区底图、专注论文数据分析与可视化输出的读者。1. 南通乡镇街道shp拿到手先分清三类文件再开工把这份rar解压后你不会只看到一个文件而是一整套后缀不同的同名文件“南通.shp”“南通各区县.shp”“南通各乡镇街道.shp”三套图层外加配套的.dbf、.prj、.shx。这套资料的层级很清晰市级边界一套、区县级一套、乡镇街道级一套正好覆盖了做区划统计和论文配图最常用的三个行政层级。我拿到数据后做的第一件事不是拖进ArcGIS乱翻而是先理清文件名后缀的含义——shapefile不是单一文件少了任何关键组件软件都会报错或读不出属性。如果你正打算做南通地区的GIS分析、专题制图或者WebGIS底图对接这份数据可以直接当作基础底图来用。2. 打开文件之前先看懂shapefile那组扩展名的分工2.1 一个shp不是一文件是七个文件的合谋许多人收到rar后直接双击.shp系统弹窗提示“无法打开”问题多半出在文件组件不完整。ESRI Shapefile是一个复合格式最少需要三个文件才能同时读出图形和属性.shp保存几何坐标、.shx建立坐标索引、.dbf用dBase表存属性记录。少了.shx部分开源库还能硬读少了.dbf你就只剩一堆没有地名的线条和多边形等于白干。下面这张表把rar里的扩展名对应清楚了扩展名文件作用是否必选.shp要素几何坐标点线面的位置都在这里必选.shx几何位置索引加快图形读取定位必选.dbf属性表存区县名、乡镇名、编码等信息必选.prj坐标参考系统描述决定数据经纬度含义强烈建议.sbn / .sbxArcGIS专用的空间索引辅助加速可选.shp.xml元数据记录数据来源和更新说明可选这套“南通各乡镇街道”压缩包里同时给出了.sbn、.sbx和.shp.xml说明数据最早是用ArcGIS整理并导出过的。如果你只打算用QGIS或Python geopandas读它.sbn和.sbx文件不会参与计算GDAL会忽略它们并在需要时自动重建索引。一个值得注意的细节是包里的“南通各区县.shp.xml”单独存在而“南通各乡镇街道.shp”没有对应自己的.xml这意味着区县图层可能是后来单独导出一份补充进去的加载后手动看一眼属性表是否含区县名字段就够了。2.2 坐标参考(.prj)决定你的数据会不会“飞”国内区划数据的坐标系统五花八门最常见的有CGCS2000EPSG:4490、西安80、WGS84甚至还有火星坐标GCJ02。直接拖进软件后边界显示在非洲旁边90%都是.prj缺失或坐标系选择错误。从这个rar的文件名看它大概率带的是CGCS2000地理坐标系但具体是4490还是某个3度分带投影不能靠猜。我的习惯是先看投影文件文本cat 南通.prj | head -c 400输出结果里如果包含GEOGCS[CGCS2000说明是经纬度坐标单位是度如果出现PROJCS[CGCS2000 / 3-degree Gauss-Kruger zone ...说明已经是投影坐标单位是米。提示之后的面积计算必须依赖投影坐标系。如果你需要在乡镇级别计算耕地面积、建成区面积请先确认.prj是投影坐标。只含GEOGCS的shp直接算面积结果会是“度²”没有实际意义。CGCS2000与WGS84之间的坐标差一般在厘米到亚米级在地市级尺度做专题图几乎不可感知但如果你把数据发布到Web地图服务GPS轨迹叠加到这份边界上可能出现几十米偏移届时再考虑转GCJ02或者加偏。2.3 不打开图形先用ogrinfo读图层户籍信息拿到shp先别急着可视化命令行里一条命令就能把数据的底细摸清ogrinfo -al -so 南通乡镇街道.shp这里的-al表示列出所有图层-so是summary-only模式只输出概要信息。你会看到Feature Count要素数量、Extent四至范围、Geometry几何类型和字段列表。对这个文件来说Feature Count应该是几十到上百的数量级对应南通各街道乡镇的个数Geometry会显示Polygon或MultiPolygon。如果嫌信息不够细再加SQL条件过滤查询ogrinfo -al -sql SELECT \乡镇\, count(*) FROM 南通乡镇街道 GROUP BY \乡镇\ 南通乡镇街道.shp这条命令用GDAL内置的SQL方言对属性表做分组统计输出结果可以用来核对有没有重名的乡镇街道记录。字段名不一定叫“乡镇”以实际输出为准SQL里字段名要加双引号避免与SQL关键字冲突。3. 加载与预处理把南通各区县和乡镇街道分开管理3.1 QGIS中解决中文乱码与坐标系错认双击文件名直接拉进QGIS很常见的情况是属性表里的中文变成“鍖椾含”一类乱码或者图层自动绑定了WGS84。前者是DBF编码没识别对后者是.prj缺失时QGIS按照默认坐标解析了。正确流程是Layer菜单 → Add Layer → Add Vector Layer在弹出的对话框里点击“Encoding”下拉框先试用“UTF-8”如果属性表仍乱码改回“GBK”或“GB2312”重新加载。DBF文件的编码声明通常写在.cpg文件里但这个rar里没有.cpg说明当初导出时没有写编码标签只能靠手动试。加载后立即做两件事验证数据可用性一是打开属性表确认区县字段、乡镇字段都是可读中文二是右键图层 → Layer CRS查看当前坐标系如果不是4326/4490而是显示“Unknown”手动指定为EPSG:4490再保存一份。3.2 用属性表分组识别区县与乡镇的层级关系乡镇街道shp和区县shp如果字段设计规范一般会有一个“区县”字段保存上级区划名一个“乡镇”字段保存本级名称。用Python直接检查分组关系很直观import geopandas as gpd town gpd.read_file(南通乡镇街道.shp, encodingutf-8) print(town.columns.tolist()) # 先看字段名 print(town[区县].value_counts()) # 每个区县包含多少个乡镇街道value_counts()的输出能帮你确认区县数量是否与南通行政区划一致同时发现某些乡镇是否被错误归类到相邻区县。如果字段名是拼音比如XZQDM、XZQM需要先自己做一个字段映射规范成区县、乡镇两个标准字段再继续操作。3.3 拓扑检查乡镇边界有没有缝隙和自相交行政区划数据最容易出现的问题是相邻面之间存在细小缝隙或者乡镇边界自相交。肉眼在屏幕上很难发现。用geopandas做一次批量有效性检查town[valid] town.geometry.is_valid print(town[valid].value_counts()) invalid town[town[valid] False] print(invalid[[乡镇]].head())is_valid返回每个要素的OGC有效性布尔值能识别自相交、环断裂等几何错误。如果发现有无效要素先用town.geometry town.geometry.buffer(0)尝试修复该操作会用0距离缓冲重建几何是GDAL/OGR生态里最常见的几何自愈手段。再检查相邻面重叠面积overlay gpd.overlay(town, town, howintersection) overlap overlay[overlay.geometry.area 1e-6] print(len(overlap))这里gpd.overlay(..., howintersection)会两两求交如果乡镇图层不存在重叠交集结果应该只有每个要素自身的面积面积很大的额外交集就说明原始数据里存在重叠面需要在分析前人工校正。4. 应用实战从乡镇面到区县面的聚合与属性连接4.1 按字段聚合(dissolve)把乡镇面合并成区县面当你只有乡镇图层却需要按区县汇总统计指标时不需要再绕路去匹配区县shp直接对乡镇面做聚合即可dissolved town.dissolve(by区县) dissolved.to_file(南通区县_合并.shp, encodingutf-8)dissolve的参数核心在by和aggfuncby指定用来聚类的字段名这里指“区县”字段aggfunc决定除几何外的属性字段如何聚合默认是first即每组取第一条记录。如果你在属性表里加了乡镇人口字段并想同时求和需要改成dissolved town.dissolve(by区县, aggfuncsum)注意aggfuncsum会对所有数值列求和包括面积字段。如果原来面积列保留的是乡镇面积聚合后会变成区县总面积这没有问题但如果是某些编码列也被识别成数值列就会出现奇怪的加和建议聚合前只保留需要的字段。4.2 空间连接把区县属性挂到乡镇边界有些乡镇图层缺少“区县”字段但区县图层里有这时用空间关系把属性补上county gpd.read_file(南通各区县.shp, encodingutf-8) joined gpd.sjoin(town, county[[geometry, 区县名]], howleft, predicatewithin)gpd.sjoin是做空间连接的核心函数howleft表示保留左侧town全部要素predicatewithin限定空间匹配关系为“乡镇面完全落在区县面内”。这个谓词对精度敏感如果乡镇边界与区县边界在原始数据里来自不同坐标系导致微小偏移within会匹配失败此时把谓词改成intersects即可它会匹配所有相交记录代价是接缝边界的乡镇可能被匹配到两个区县需要groupby后去重。4.3 坐标系转换CGCS2000转成WGS84再输出WebGIS、高德地图或者与GPS数据叠加时常需要把投影坐标或2000系转换成WGS84经纬度town_geo town.to_crs(EPSG:4326) town_geo.to_file(南通乡镇街道_wgs84.shp, encodingutf-8)to_crs(EPSG:4326)等价于转成WGS84地理坐标系输出经纬度小数。如果用于前端Leaflet/Cesium展示这一步足够。如果需要在转换后做距离和面积量算再投影回EPSG:3857Web Mercator即可注意3857的面积数值会随纬度变化只适合出图不建议作统计依据。4.4 批量导出按区县拆分乡镇街道图层做分县专题图时按区县把乡镇街道拆成独立shp是高频需求。用循环加groupby一行搞定import os os.makedirs(out, exist_okTrue) for name, part in town.groupby(区县): part.to_file(fout/{name}.shp, encodingutf-8)groupby(区县)按区县分组part是每组子集to_file时就写入独立文件。这里最关键的坑是输出目录不能放在数据文件所在目录内否则循环过程中产生的子集shp可能会被下一轮读取逻辑当作输入数据重复纳入导致分组无限增长。我一般把输出目录建到/tmp或项目独立目录下跑完再拷回去。5. 进阶收尾shp转TXT、KML与GeoJSON的几种姿势和验证5.1 shp转GeoJSON保留属性和编码最稳的命令GeoJSON是Web前端的通用格式GDAL自带命令一行转换ogr2ogr -f GeoJSON 南通.unjs.geojson 南通乡镇街道.shp -lco ENCODINGUTF-8-f指定输出格式-lco ENCODINGUTF-8要求输出文件按UTF-8编码属性保证前端显示中文不乱码。如果你的坐标是GCJ02加密过或者担心前端地图叠加偏移可以再加-t_srs EPSG:4326强制重投影。5.2 批量转KML保留中文地名需要增删Name元素乡镇边界转到KML后放在Google Earth里查看或做汇报演示一条命令能转但中文名问题需要处理ogr2ogr -f KML 南通.kml 南通乡镇街道.shp用默认参数转换后KML的Placemark名称会取自属性表的第一个字符串字段中文大多能保留如果出现乱码常见做法是先转成GeoJSON再用Python的simplekml库构造KML并显式指定name字段import simplekml kml simplekml.Kml() for row in town.itertuples(): p kml.newpolygon(namegetattr(row, 乡镇)) p.outerboundaryis list(row.geometry.exterior.coords) kml.save(南通.kml)newpolygon创建面要素outerboundaryis接收外环坐标列表name字段显式传入中文乡镇名绕过了GDAL默认取首字段的逻辑。5.3 shp转TXT把面坐标和属性落盘用于论文附录论文附图或数据说明需要把坐标信息导出成明文TXT时按要素逐个写出坐标点集是可靠方案with open(南通坐标.txt, w, encodingutf-8) as f: for row in town.itertuples(): f.write(f{getattr(row, 乡镇)}\n) f.write(str(list(row.geometry.exterior.coords))) f.write(\n)geometry.exterior.coords取出面的外环坐标序列list()转成可写的点列表。对带洞的面interiors里还有内环坐标如需一并输出需再循环一次。导出的TXT可直接作为论文附录里的数据来源说明。最后的验证方法是统计转出的KML与TXT的记录数量是否等于原shp的要素数grep -c Placemark 南通.kml wc -l 南通坐标.txtgrep -c统计Placemark标签个数与len(town)核对TXT的行数则能反推出是否漏写了某个乡镇。三层格式互相校验能发现绝大多数导出丢要素的问题比肉眼在软件里翻图层可靠得多。本文还有配套的精品资源点击获取
返回列表