ARTICLE DETAIL

资讯详情

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

江苏省村界shp数据实战:从加载、坐标转换到渔网分割与WKT导出

江苏省村界shp数据实战:从加载、坐标转换到渔网分割与WKT导出 简介这份2025年江苏省村界村级行政区划矢量数据面向GIS从业者、国土规划人员及区域发展研究者用于解决行政村边界获取难、行政层级不完整的问题。数据覆盖村、社区乡、街道镇、市等多级区划边界以面要素矢量图形呈现并附带名称、行政代码、隶属关系等属性字段可支撑空间分析与专题制图。资源包共6个文件约24.92MB以Shapefile标准格式组织包含shp矢量数据、shx索引、dbf属性表、prj坐标系统、cpg字符编码及shp.xml元数据主流GIS软件均可直接打开使用。目前已有340人学习下载。凭借数万个面要素的高精度划分该数据能反映江苏各行政村最新边界变化适用于国土规划、城乡建设、交通物流、农业规划与应急管理等领域为区域协调、人口资源管理及乡村振兴研究提供可靠的空间底图与决策依据。1. 江苏省村界矢量数据从找数据到能落库的那条最短路径做空间分析的人迟早会撞上同一个需求手头有一份业务数据字段里只有“江苏省南京市江宁区秣陵街道某某村”但你需要把它落到地图上算出每个村的面积、相邻关系、到最近道路的距离。这时候你缺的不是算法而是一份能用的村级行政区划矢量数据。江苏省村界村级行政区划矢量 shp 数据说的就是把全省行政村含社区、涉农居委会的边界以 shapefile 格式组织成一套可以直接进 GIS 或数据库的空间数据。它解决的核心问题是让“村”这个最小治理单元从一串文字变成有坐标、有拓扑、有属性表的几何对象。这类数据适合谁做国土空间规划、乡村振兴评估、快递物流分区、农业遥感统计、应急物资投放的人都需要村级边界作为统计单元。新手拿到 shp 文件后往往卡在坐标系对不上、字段乱码、边界重叠这三件事上熟手更关心的是数据现势性、村级单元是否合并、属性表里有没有行政区代码。下面按“先搞清楚数据长什么样再动手把它跑通最后避开那些让人返工的坑”这条线展开中间会穿插 shp 转 txt、渔网分割 shp、shp 格式矢量数据导出为 wkt 这些实际会碰到的操作。2. 江苏省村界 shp 数据到底包含什么图层、字段与坐标系2.1 一个村界 shp 文件通常由哪几个文件组成shapefile 不是单个文件而是一组同名文件的集合。拿到“江苏省村界”这类数据时你至少会看到下面这些扩展名。缺任何一个GIS 软件都可能打不开或者属性丢失。文件扩展名作用缺失后果.shp存储几何形状点、线、面无法显示图形.shx几何索引加快查询部分软件报错或加载慢.dbf属性表存村名、代码等只剩图形没有村名.prj坐标系定义坐标对不上无法叠加.cpg字符编码说明中文村名变乱码常见做法是把这一组文件放在同一个文件夹里文件名保持一致不要只拷贝 .shp 出去。我一般会先检查 .prj 里写的是什么坐标系江苏省的村级数据多数是 CGCS2000 或 WGS84 地理坐标系也有部分加工过的数据用投影坐标系单位是米。2.2 属性表里哪些字段决定你能不能直接用打开属性表重点看这几类字段。不同来源的数据字段名不一样但逻辑相通。行政区代码通常是 12 位或 17 位前 6 位是县区中间是乡镇后面是村。这个字段是关联统计数据的钥匙。村名中文名称注意有没有“村委会”“社区”“涉农居委会”等后缀差异。上级区划有的数据会带乡镇名、区县名方便做分组统计。面积字段可能是预先算好的也可能是你后面自己算。如果属性表里只有村名没有代码做汇总时很容易因为重名翻车。江苏村级重名不算少比如“新桥村”“双桥村”在不同县区都有。所以拿到数据后第一件事是确认有没有唯一代码字段。2.3 坐标系选错会带来什么连锁反应坐标系是村界数据里最容易被忽略、后果最严重的一项。地理坐标系如 CGCS2000的单位是度投影坐标系如 UTM 或高斯克吕格的单位是米。如果你拿地理坐标系的数据去算面积得到的数值单位是“平方度”没有任何业务意义。判断方法很简单在 GIS 里看图层属性或者直接读 .prj 文件内容。如果里面出现GCS_China_Geodetic_Coordinate_System_2000或WGS_1984就是地理坐标系如果出现Transverse_Mercator或Gauss_Kruger就是投影坐标系。江苏省常用的投影是 CGCS2000 3 度带高斯克吕格中央经线按 117E、120E 分带。提示如果数据是地理坐标系先做投影转换再算面积。不要直接改 .prj 文件里的字符串那只是改标签不改坐标值。3. 把村界 shp 跑通的最小操作链从加载到导出3.1 用 Python 读取村界 shp 并检查字段与坐标系下面这段代码用 geopandas 读取 shp打印坐标系、字段名、前几行属性并检查几何是否有效。这是我在拿到任何一份新 shp 数据后都会跑一遍的“体检脚本”。import geopandas as gpd # 读取江苏省村界 shp注意路径不要有中文和空格 gdf gpd.read_file(rD:\data\jiangsu_village.shp) # 打印坐标系 print(坐标系:, gdf.crs) # 打印字段名和类型 print(字段:, gdf.dtypes) # 打印前 5 行属性重点看村名和代码 print(gdf.head()) # 检查几何是否有效无效几何会导致后续空间运算报错 invalid gdf[~gdf.geometry.is_valid] print(无效几何数量:, len(invalid)) # 检查是否有空几何 empty gdf[gdf.geometry.is_empty] print(空几何数量:, len(empty))逻辑说明gpd.read_file会自动读取同目录下的 .dbf 和 .prj。gdf.crs返回坐标系对象如果返回 None说明 .prj 缺失或未被识别。is_valid检查多边形是否自相交、是否有重复节点村级边界数据因为来源多样经常出现自相交。is_empty检查有没有空几何对象。参数说明路径用原始字符串r...避免转义。如果数据量大read_file会占用较多内存可以加rows1000先读一部分做检查。字段类型里object通常是字符串float64是数值geometry是几何列。3.2 用 QGIS 加载并做一次可视化检查不是所有人都习惯命令行QGIS 是检查村界数据最直观的工具。步骤很短打开 QGIS选择“图层”-“添加图层”-“添加矢量图层”。浏览到 shp 文件所在目录选中 .shp 文件点击“添加”。右键图层选择“属性”-“信息”查看坐标系和要素数量。右键图层选择“打开属性表”检查村名字段是否乱码。如果乱码在图层属性里找到“源”-“数据源编码”改成 GBK 或 UTF-8 再重新加载。可视化检查的重点是看边界有没有明显错位、有没有大面积空白、有没有重复叠加。江苏省村界数据如果来自不同年份的行政区划调整可能会出现某个村被拆分后新旧边界同时存在的情况。这时候需要根据行政区代码去重。3.3 把 shp 导出为 txt 或 wkt 的两种常见做法有些业务系统不直接吃 shp需要把几何转成文本。shp 转 txt 和 shp 格式矢量数据导出为 wkt 是热搜里经常出现的操作。下面用 Python 把每个村的边界转成 WKT 字符串并写入 txt 文件。import geopandas as gpd gdf gpd.read_file(rD:\data\jiangsu_village.shp) # 只保留村名、代码和几何列 gdf gdf[[village_name, code, geometry]] # 将几何转为 WKT 字符串 gdf[wkt] gdf.geometry.apply(lambda geom: geom.wkt) # 导出为 txt每行一个村字段用竖线分隔 with open(rD:\data\village_wkt.txt, w, encodingutf-8) as f: for _, row in gdf.iterrows(): f.write(f{row[code]}|{row[village_name]}|{row[wkt]}\n) print(导出完成共, len(gdf), 条)逻辑说明geom.wkt把多边形转成POLYGON((...))格式的字符串。写入时用竖线分隔避免 WKT 里的逗号和括号干扰解析。如果目标系统需要 JSON 格式可以用geom.__geo_interface__转成字典再序列化。参数说明encodingutf-8保证中文村名不乱码。如果 txt 要导入数据库注意 WKT 字符串可能很长字段类型要设成 text 或 clob。导出前建议先做一次gdf gdf[gdf.geometry.notna()]排除空几何。3.4 用渔网分割 shp 做网格化统计的前置操作渔网分割 shp 是另一个高频需求把村界和规则网格叠加统计每个网格里有多少个村或者把村界切成小方块做采样。下面用 geopandas 生成渔网并做叠加。import geopandas as gpd from shapely.geometry import box import numpy as np gdf gpd.read_file(rD:\data\jiangsu_village.shp) # 先投影到米制坐标系方便按固定距离生成渔网 gdf_m gdf.to_crs(epsg4547) # CGCS2000 3度带江苏适用 # 获取整体范围 minx, miny, maxx, maxy gdf_m.total_bounds # 生成 1km x 1km 渔网 cell_size 1000 cols np.arange(minx, maxx, cell_size) rows np.arange(miny, maxy, cell_size) cells [] for x in cols: for y in rows: cells.append(box(x, y, x cell_size, y cell_size)) grid gpd.GeoDataFrame({geometry: cells}, crsgdf_m.crs) # 空间叠加保留落在村界内的网格 intersect gpd.overlay(grid, gdf_m, howintersection) print(原始网格数:, len(grid)) print(与村界相交的网格数:, len(intersect))逻辑说明to_crs(epsg4547)把地理坐标系转成米制投影这样渔网间距才是真实的 1 公里。total_bounds返回整个图层的范围。box生成矩形网格。gpd.overlay做相交运算只保留与村界有重叠的网格。参数说明cell_size按业务定做村级统计一般用 500 米到 2 公里。epsg4547是 CGCS2000 3 度带中央经线 117E 的 EPSG 代码江苏北部适用南部可以用 4548 或 4549。如果数据本身已经是投影坐标系跳过to_crs。4. 村界数据落地时的避坑与排查4.1 中文村名乱码现象、原因与解决现象QGIS 或 Python 打开属性表村名显示为“汊苏省”这类字符。原因.dbf 文件的默认编码是 GBK但读取时被当成 UTF-8 解析。解决在 QGIS 里改数据源编码为 GBK在 Python 里用gpd.read_file(..., encodinggbk)。如果 .cpg 文件存在且写着 UTF-8但实际是 GBK以实际为准改 .cpg 内容或读取时强制指定。4.2 边界重叠与缝隙村级数据最常见的拓扑问题现象两个相邻村的多边形有重叠区域或者中间有一条细缝。原因数据来自不同批次数字化或者行政区划调整后没有做拓扑重建。解决用gdf.geometry gdf.geometry.buffer(0)修复自相交用gpd.overlay做 union 后再按村代码融合缝隙如果影响面积统计可以用snap工具把节点吸附到容差范围内。我一般会先跑一次is_valid把无效几何单独导出检查。4.3 坐标系缺失或错误面积算出来差几个数量级现象算出的村面积是 0.0001 或者 1e10 这种离谱数值。原因地理坐标系下直接算面积单位是平方度或者 .prj 文件丢失软件默认按 WGS84 处理但实际是其他坐标系。解决先确认 .prj 存在且内容正确再用to_crs转到米制投影。如果 .prj 丢失根据数据来源判断坐标系江苏村级数据多数是 CGCS2000可以手动指定crsEPSG:4490后再投影。4.4 行政区代码重复或缺失关联统计数据时对不上现象用村代码关联人口、经济数据时发现有些村匹配不上或者一个代码对应多条记录。原因数据里存在历史代码和现行代码混用或者代码字段有空格、前导零丢失。解决把代码字段转成字符串用str.strip()去空格用str.zfill(12)补前导零。如果确实有重复按面积最大或现势性最新的记录保留。4.5 数据现势性与行政区划调整别拿五年前的村界做今年的统计现象某个村在 2023 年已经合并到另一个村但数据里还是两个独立多边形。原因数据版本旧没有跟上行政区划调整。解决找最新的行政区划代码表做比对把已撤销的村代码标记出来做融合或剔除。如果只是做趋势分析可以在文档里注明数据年份如果做考核统计必须用最新边界。5. 让村界数据真正可用的三个进阶习惯5.1 建立一套可复用的数据检查清单我现在的习惯是任何一份村级 shp 进库前先跑一个检查脚本输出下面这张表。这个习惯帮我省掉了大量返工时间。检查项检查方法通过标准坐标系读 .prj 或 gdf.crs有明确 CRS非 None几何有效性gdf.geometry.is_valid无效几何占比低于 1%空几何gdf.geometry.is_empty空几何数量为 0村代码唯一性gdf[code].duplicated().sum()重复数为 0村名乱码抽样打印中文正常显示面积合理性投影后算面积无负值、无异常大值这张表可以直接写成 Python 函数每次读数据后调用。检查不通过就先修复不要带着问题往下做。5.2 把村界和业务数据做空间关联的稳妥方式村界数据最终要落到“每个村有多少人、多少企业、多少耕地”这类统计上。稳妥的做法是先把业务数据做地理编码或空间落点再用sjoin做空间关联最后按村代码汇总。不要用村名做关联键重名问题会让你在汇总阶段翻车。如果业务数据只有地址文字先用地理编码服务转成点再和村界面做within判断。import geopandas as gpd village gpd.read_file(rD:\data\jiangsu_village.shp) points gpd.read_file(rD:\data\business_points.shp) # 统一坐标系 points points.to_crs(village.crs) # 空间关联判断每个点落在哪个村 joined gpd.sjoin(points, village, howleft, predicatewithin) # 按村代码统计点数 count_by_village joined.groupby(code).size().reset_index(namepoint_count) print(count_by_village.head())逻辑说明sjoin的predicatewithin表示点完全落在村多边形内部。howleft保留没有匹配到村的点方便排查。groupby(code)按村代码汇总。参数说明如果点数据量大先建空间索引geopandas 会自动处理。predicate还可以用intersects但within更严格适合点落村场景。5.3 一个让我少加三天班的小技巧先做小范围验证再全省跑江苏省有上万个村级单元全省数据跑一次空间运算可能要几分钟到十几分钟。我的习惯是先选一个县或一个乡镇的范围把整个流程跑通确认字段、坐标系、关联逻辑都没问题再放开到全省。这个习惯来自一次血泪经验当时直接拿全省村界做叠加跑了二十分钟才发现坐标系没转所有面积都是错的只能重来。现在我会在脚本开头加一个TEST_MODE开关先用 100 条记录验证通过后再全量执行。希望帮到你。本文还有配套的精品资源点击获取
返回列表