ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

2020-2022年成都市矢量数据获取、清洗与GIS空间分析实战

2026/10/7 3:28:04 拓冰建站 浏览量
2020-2022年成都市矢量数据获取、清洗与GIS空间分析实战 简介这份2020—2022年成都市矢量数据资源面向GIS从业者、城市规划研究者、交通与水文分析人员及地图应用开发者提供覆盖成都全域的多要素空间数据可用于空间分析、地图制图与决策支持。压缩包共229个文件约95.58MB以shp、shx、dbf、prj等Shapefile核心格式为主辅以sbx、sbn空间索引、cpg编码说明另含xlsx统计表、xml元数据及tif、tfw、ovr栅格文件兼顾矢量与高程数据。内容涵盖路网城市道路、铁路、高速、国道、省道、县道、乡道、河流水系、建筑轮廓、省市县乡镇行政区划及十万级POI兴趣点并附DEM数字高程模型可支撑交通规划、洪水预警、日照分析、商业选址与公共服务布局等场景。目前已有1673人学习下载适合需要完整成都空间底图、开展区域研究与智慧城市系统搭建的读者参考使用。1. 成都市矢量数据从2020到2022一套能直接进GIS的底图怎么攒出来手上接过一个成都本地的选址分析需求甲方开口就要“最近三年的路网、地块和行政区划能直接拖进ArcGIS那种”。翻了一圈公开渠道2020到2022年这个时间窗其实很尴尬全国性数据更新节奏慢地方性数据又散在各处坐标系、字段名、边界口径全对不上。所谓“2020-2022年成都市矢量数据”落到实操层面就是一套覆盖这三年、空间参考统一、属性字段可读、能支撑空间查询与制图的矢量图层集合通常包含行政区划、道路、水系、兴趣点、用地地块这几类。它解决的是“底图从哪来、怎么对齐、怎么保证时间口径一致”的问题适合做城市分析、选址评估、规划前期研究的人。下面按我实际攒数据的顺序讲不绕弯子。2. 先搞清楚要哪些图层成都市矢量数据的图层清单与字段设计2.1 五类核心图层少一个都影响后续分析成都市矢量数据不是单一文件而是一组按主题拆分的图层。2020-2022这个时间窗内我一般会准备这几类行政区划市、区县、街道三级边界用于裁剪和统计汇总。道路网络高速、主干道、次干道、支路带道路等级和名称字段。水系河流、湖泊、渠道用于缓冲分析和景观评估。兴趣点学校、医院、商场、地铁站用于可达性计算。用地地块居住、商业、工业、绿地用于功能混合度分析。这五类覆盖了大多数空间分析场景。如果只做路网分析可以砍掉用地地块如果做公共服务设施评估兴趣点和行政区划是底线。2.2 字段设计别等合并时才后悔字段名不统一字段设计是后面所有麻烦的根源。我踩过的坑是不同来源的区县边界一个用“NAME”一个用“name”一个用“区县名称”合并时全乱。统一字段规范如下字段名类型含义示例adcode文本行政区划代码510104name文本名称锦江区level文本层级districtyear整数数据年份2021geom_type文本几何类型polygonyear字段是2020-2022这套数据的关键。同一个图层里不同年份的边界可能微调必须用年份字段区分否则做时间对比时会出现“同一块地两年面积不一样”的玄学问题。提示字段名一律用英文小写加下划线避免中文和空格。GIS软件对中文字段的支持时好时坏导出GeoJSON时尤其容易翻车。2.3 坐标系选择成都本地用CGCS2000还是WGS84成都市矢量数据的坐标系选择直接影响面积和距离计算精度。常见做法是存储和交换用EPSG:4326WGS84经纬度通用性好。做面积统计和距离量算时投影到EPSG:4544CGCS2000 3度带中央经线105°E单位是米。我一般会存两份一份4326用于展示和叠加在线底图一份4544用于计算。转换用QGIS或GDAL一行命令的事但如果不转直接算面积结果会偏到让你怀疑人生。# 把WGS84的成都矢量数据投影到CGCS2000 3度带 ogr2ogr -f ESRI Shapefile \ -t_srs EPSG:4544 \ chengdu_4544.shp \ chengdu_4326.shp-t_srs指定目标坐标系EPSG:4544对应中央经线105°E覆盖成都全域。转换后面积字段单位从度变成米后续统计才靠谱。3. 数据从哪来2020-2022年成都市矢量数据的获取与整理路径3.1 公开渠道的取舍哪些能用哪些只能参考2020-2022年成都市矢量数据的来源大致分三类第一类是全国性基础地理数据覆盖全但更新慢2020年的版本可能反映的是2018年的现状。第二类是地方公开的专题数据比如规划部门发布的用地图层精度高但年份不全。第三类是开放地图数据路网和兴趣点更新快但边界和属性需要清洗。我的策略是行政区划用全国性基础数据保证边界权威路网和兴趣点用开放地图数据补时效用地地块尽量找地方公开版本。三者叠加前统一坐标系和字段。3.2 用Python批量读取和合并多源矢量数据拿到手的文件格式五花八门Shapefile、GeoJSON、KML都有。用GeoPandas统一读进来按图层类型合并。import geopandas as gpd import pandas as pd from pathlib import Path # 定义各图层的数据目录 layer_dirs { boundary: data/boundary, road: data/road, water: data/water, poi: data/poi, landuse: data/landuse } def load_layer(layer_name, year): 读取指定图层和年份的所有矢量文件并合并 files list(Path(layer_dirs[layer_name]).glob(f*{year}*.shp)) if not files: print(f警告{layer_name} {year}年无数据) return None gdfs [gpd.read_file(f) for f in files] merged pd.concat(gdfs, ignore_indexTrue) merged gpd.GeoDataFrame(merged, crsgdfs[0].crs) merged[year] year merged[layer] layer_name return merged # 按年份循环读取 all_data {} for year in [2020, 2021, 2022]: for layer in layer_dirs: gdf load_layer(layer, year) if gdf is not None: all_data[f{layer}_{year}] gdf print(f{layer} {year}: {len(gdf)} 条记录)这段代码的核心逻辑是按图层名和年份匹配文件合并后统一写入year和layer字段。glob模式*{year}*要求文件名里带年份所以下载数据时就要把年份写进文件名比如road_2021.shp。如果文件名不规范先批量重命名再跑。参数上ignore_indexTrue避免索引重复crsgdfs[0].crs以第一个文件的坐标系为准。如果各文件坐标系不一致这里会埋雷所以合并前最好先检查一遍。3.3 数据清洗去重、补字段、修几何合并后的数据常见问题有三个重复记录、字段缺失、几何无效。处理顺序不能乱先修几何再分析。from shapely.validation import make_valid def clean_gdf(gdf): 清洗矢量数据去重、修几何、补字段 # 按几何和名称去重 gdf gdf.drop_duplicates(subset[name, geometry]) # 修复无效几何 gdf[geometry] gdf[geometry].apply( lambda geom: make_valid(geom) if geom and not geom.is_valid else geom ) # 删除几何为空的记录 gdf gdf[gdf[geometry].notna()] # 补充缺失的year字段 if year not in gdf.columns: gdf[year] 2020 return gdf for key in all_data: all_data[key] clean_gdf(all_data[key]) print(f{key} 清洗后: {len(all_data[key])} 条)make_valid是Shapely 1.8以上版本的方法能把自相交的多边形修成合法几何。如果版本低用buffer(0)替代但效果差一些。去重时用name加geometry组合避免同名不同位置的道路被误删。注意几何修复会改变顶点坐标如果后续要做精确的面积对比修复前后要记录差异。我一般会保留一份原始数据不动清洗结果另存。4. 把数据用起来成都市矢量数据的空间分析与可视化4.1 用行政区划裁剪得到成都全域分析范围所有分析第一步把数据裁到成都市范围内。用行政区划图层做裁剪避免周边城市的数据干扰。# 读取成都市边界 city_boundary all_data[boundary_2021] city_boundary city_boundary[city_boundary[level] city] city_geom city_boundary.geometry.unary_union # 裁剪路网 road_2021 all_data[road_2021] road_chengdu road_2021[road_2021.intersects(city_geom)].copy() road_chengdu[geometry] road_chengdu.geometry.intersection(city_geom) print(f裁剪后路网: {len(road_chengdu)} 条)unary_union把多个区县边界合并成一个整体intersection做几何裁剪。注意裁剪后几何类型可能从线变成多线后续做长度统计时要用length属性而不是简单计数。4.2 道路密度计算投影坐标系下的网格统计道路密度是选址分析的常用指标。做法是生成渔网网格统计每个网格内的道路总长度除以网格面积。import numpy as np # 投影到4544 road_proj road_chengdu.to_crs(epsg4544) city_proj city_boundary.to_crs(epsg4544) # 生成500米网格 xmin, ymin, xmax, ymax city_proj.total_bounds grid_size 500 cols int((xmax - xmin) / grid_size) 1 rows int((ymax - ymin) / grid_size) 1 from shapely.geometry import Polygon grids [] for i in range(cols): for j in range(rows): x0 xmin i * grid_size y0 ymin j * grid_size grids.append(Polygon([(x0, y0), (x0grid_size, y0), (x0grid_size, y0grid_size), (x0, y0grid_size)])) grid_gdf gpd.GeoDataFrame(geometrygrids, crsEPSG:4544) grid_gdf gpd.clip(grid_gdf, city_proj) # 计算每个网格的道路长度 road_proj[length] road_proj.geometry.length joined gpd.sjoin(road_proj, grid_gdf, howinner, predicateintersects) density joined.groupby(index_right)[length].sum().reset_index() grid_gdf grid_gdf.reset_index().rename(columns{index: index_right}) grid_gdf grid_gdf.merge(density, onindex_right, howleft) grid_gdf[length] grid_gdf[length].fillna(0) grid_gdf[density] grid_gdf[length] / (grid_size * grid_size)total_bounds拿到成都全域的投影坐标范围grid_size500对应500米网格。sjoin做空间连接把每条道路的长度归属到相交的网格。最后density单位是米/平方米乘以10000就是米/公顷更符合规划习惯。参数上网格大小决定分析粒度500米适合区级分析200米适合街道级1000米适合市域概览。改grid_size就行但网格越小计算量越大成都全域500米网格大概几万个跑起来还能接受。4.3 用QGIS出图样式配置和标注技巧分析结果最终要出图。QGIS里加载清洗后的矢量数据按以下步骤配置第一步设置项目坐标系为EPSG:4544保证距离和面积显示正确。第二步道路图层按level字段分类渲染高速用粗红线主干道用橙色支路用灰色细线。第三步行政区划图层只保留边界填充设为透明标注用name字段。第四步道路密度网格用渐变色从浅绿到深红透明度设60%避免遮挡底图。标注冲突是常见问题。QGIS的标注引擎里把“冲突处理”设为“阻止重叠”优先级按道路等级排序。如果标注还是挤用“标注缓冲区”给文字留空间。提示出图前把year字段过滤到单一年份否则2020和2021的边界叠在一起图面会乱。我一般一个年份存一个QGIS工程文件省得来回切。5. 避坑与排查成都市矢量数据实操中的五个血泪教训5.1 坐标系混用导致面积翻倍现象同一块用地在4326下算面积是0.003在4544下是30000差了七个数量级。原因4326的单位是度度的平方不能直接当面积用。解决所有面积和距离计算前先to_crs(epsg4544)养成习惯后就不会忘。5.2 年份字段缺失导致时间对比失效现象合并2020和2021的区县边界后发现锦江区的面积变了但实际边界没动。原因合并时没写year字段两条记录混在一起去重时随机保留了一条。解决读取每个文件时强制写入年份合并后按year分组检查记录数。5.3 几何无效导致空间连接报错现象sjoin跑到一半报TopologyException提示自相交。原因下载的多边形数据有自相交或重复顶点。解决合并后立即跑make_valid不要等到分析时才修。如果数据量大用gdf.geometry.is_valid.all()先检查False的再修。5.4 字段名中文导致GeoJSON导出乱码现象导出GeoJSON后属性表里的“名称”变成“\u540d\u79f0”。原因GeoJSON规范建议用ASCII字段名中文会被转义。解决统一用英文小写字段名中文名称放name_cn字段导出时用ensure_asciiFalse参数。5.5 道路重复导致密度虚高现象道路密度图上有几条走廊特别红实际去现场看没那么多路。原因开放地图数据里同一条路被拆成多段或者双向车道各存一条。解决按name和geometry去重后再按name合并同一道路的多段用dissolve按名称融合。# 按道路名称融合消除分段重复 road_dissolved road_chengdu.dissolve(byname, aggfuncfirst).reset_index() print(f融合后道路: {len(road_dissolved)} 条)dissolve把同名道路合并成一条aggfuncfirst保留第一条记录的属性。融合后长度统计更接近实际。6. 进阶技巧用2020-2022三年数据做变化检测6.1 用地地块的年度变化对比三年数据最大的价值是做变化检测。以用地地块为例对比2020和2022的图层找出功能变更的地块。# 读取两年用地数据 landuse_2020 all_data[landuse_2020].to_crs(epsg4544) landuse_2022 all_data[landuse_2022].to_crs(epsg4544) # 空间连接找出重叠地块 overlay gpd.overlay(landuse_2020, landuse_2022, howintersection, suffixes(_20, _22)) # 筛选功能变更的地块 changed overlay[overlay[type_20] ! overlay[type_22]] changed[change_area] changed.geometry.area changed changed[changed[change_area] 1000] # 过滤小于1000平方米的碎片 print(f功能变更地块: {len(changed)} 块) print(changed[[name_20, type_20, type_22, change_area]].head(10))overlay的intersection模式保留两年地块的重叠部分suffixes区分同名字段。筛选条件change_area 1000过滤掉边界微调产生的碎片只保留实质性变更。输出结果可以直接做成变更地图标注变更前后的功能类型。6.2 道路网络的年度扩展分析路网变化反映城市扩张方向。对比2020和2022的道路图层找出新增道路。# 找出2022年新增的道路 road_2020_union all_data[road_2020].to_crs(epsg4544).geometry.unary_union road_2022 all_data[road_2022].to_crs(epsg4544) # 2022年道路中不与2020年重叠的部分 new_roads road_2022[~road_2022.intersects(road_2020_union)] new_roads[length] new_roads.geometry.length total_new new_roads[length].sum() / 1000 # 转公里 print(f2020-2022新增道路: {total_new:.1f} 公里)~取反intersects判断是否与2020年路网相交。新增道路按长度汇总可以进一步按区县分组看哪个区扩张最快。这个结果和规划部门的年度报告对照能验证数据时效性。6.3 一个我常犯的错误忽略数据年份的“名义”和“实际”最后说个教训。2020-2022年成都市矢量数据里文件名写的年份不一定是数据实际反映的年份。我遇到过标着2021的用地数据实际是2019年的调查结果只是2021年才发布。后来我养成了习惯拿到数据先看属性表里有没有survey_year或update_date字段没有的话用路网和兴趣点做交叉验证——如果某年的路网里有一条2022年才通车的高速那这份数据至少更新到2022年。这个验证方法不复杂但能省掉很多返工。希望帮到你。本文还有配套的精品资源点击获取