首页 / 资讯中心 / 文章详情

全国铁路矢量数据集处理指南:从解压到空间分析

全国铁路矢量数据集处理指南:从解压到空间分析 ★ FEATURED ARTICLE
简介这份2024年全国铁路矢量数据集面向GIS分析、交通规划、地图可视化及城市研究方向的从业者与学习者提供覆盖全国范围的铁路与城市轨道交通空间数据可用于路网密度分析、可达性评估、专题制图等场景。资源包共48个文件以shp、shx、dbf、prj、cpg等Shapefile标准组件为主另含xml元数据及sbx、sbn空间索引文件压缩包约63.35MB解压后数据量约136MB便于在ArcGIS、QGIS等平台直接加载。数据内容涵盖铁路、高铁、地铁、有轨电车、轻轨、单轨铁路、窄轨铁路、微型火车网络及缆索铁道等多种类型分类细致属性表与投影信息完整可直接用于空间统计与制图输出。目前已有883人学习下载适合需要全国尺度轨道交通底图的研究者与制图人员参考使用。1. 拿到一份全国铁路矢量数据集先别急着往地图里拖很多人第一次接触「2024年全国铁路铁路、高铁、地铁矢量数据集.7z」这类资源第一反应是解压、拖进 GIS 软件、看线条铺满全国然后就没有然后了。真正做过交通分析的人会先问三个问题这份数据分了几层、坐标系是什么、属性字段能不能区分高铁和普速。因为铁路矢量数据最坑的地方从来不是「有没有」而是「混在一起」。高铁、普速铁路、地铁在几何上都是线但业务含义完全不同——高铁要看走向和站点间距地铁要看城市内部线网密度普速铁路要看货运通道。如果拿到手不先分层后面所有分析都是错的。这篇笔记面向做交通规划、城市研究、地图可视化的从业者把这份数据从解压到出图、从字段清洗到空间分析的完整路径讲清楚中间会给出可直接复现的代码和参数也会把踩过的坑摊开说。2. 解压之后先看什么图层结构与坐标系判定2.1 7z 包解开后常见的文件形态这类全国范围的矢量数据集打包成 .7z 通常是为了压缩体积解压后大概率是 Shapefile.shp/.shx/.dbf/.prj或者 GeoPackage.gpkg少数情况是 GeoJSON。Shapefile 的问题是单文件字段名限制 10 个字符、编码容易乱GeoPackage 则把图层、坐标系、属性都装在一个文件里更适合后续处理。我一般会先解压到一个纯英文路径下避免中文路径导致 GDAL 读取失败。# 解压到指定目录-o 指定输出路径-y 覆盖已有文件 7z x 2024年全国铁路矢量数据集.7z -o./rail_data -y # 查看解压后的文件结构 find ./rail_data -type f | head -50解压后不要急着打开先用ogrinfo看一眼图层清单和坐标系。GDAL 的ogrinfo是判断数据质量的第一个关口它能告诉你每个图层的几何类型、要素数量、坐标系定义。# 列出数据源中所有图层 ogrinfo -so ./rail_data/railway.gpkg # 查看某个图层的详细信息包括坐标系和字段 ogrinfo -so ./rail_data/railway.gpkg high_speed_rail如果输出里坐标系显示为GCS_WGS_1984或EPSG:4326说明是经纬度坐标适合做全国尺度展示如果显示CGCS2000或投影坐标如EPSG:3857那就要注意后续面积、长度计算时的单位问题。全国尺度的铁路数据常见做法是存 WGS84 经纬度做长度统计时再投影到等距坐标系。2.2 坐标系不一致会带来什么后果我见过最典型的一次翻车把高铁图层和地铁图层叠在一起发现地铁线全部偏移到城市外面去了。原因是一个是 WGS84一个是 GCJ02火星坐标。国内很多地图数据来源不同坐标系混用是常态。判断方法很简单用 Python 读两个图层的 CRS 对比一下。import geopandas as gpd # 读取两个图层 hsr gpd.read_file(./rail_data/railway.gpkg, layerhigh_speed_rail) metro gpd.read_file(./rail_data/railway.gpkg, layermetro) print(高铁坐标系:, hsr.crs) print(地铁坐标系:, metro.crs) print(高铁要素数:, len(hsr)) print(地铁要素数:, len(metro)) # 如果坐标系不一致统一到 WGS84 if hsr.crs ! metro.crs: metro metro.to_crs(hsr.crs) print(已统一坐标系)参数说明to_crs()是 GeoPandas 的坐标转换方法传入目标 CRS 即可。注意如果源数据没有 CRS 定义crs 为 None需要先用set_crs()手动指定否则转换会报错。这一步做完至少保证所有图层在同一空间参考下后面叠加分析才不会出现「线飘到海里」的玄学问题。2.3 属性字段决定这份数据能不能用图层分对了、坐标系统一了接下来看属性表。铁路数据的核心字段通常包括线路名称、类型高铁/普速/地铁、等级、是否电气化、开通年份等。但很多数据集字段名是拼音缩写或者英文简写比如LXMC路线名称、LXDJ路线等级需要先做字段映射。# 查看字段名和前几行数据 print(hsr.columns.tolist()) print(hsr.head(3)) # 常见字段重命名映射 rename_map { LXMC: line_name, LXDJ: line_level, LX_TYPE: line_type, KHTIME: open_year } hsr hsr.rename(columns{k: v for k, v in rename_map.items() if k in hsr.columns}) print(hsr.columns.tolist())如果字段里没有区分高铁和普速的标识那就只能靠线路名称关键词来推断比如含「高铁」「客运专线」的归为高铁含「铁路」但不含「高铁」的归为普速。这种做法有误差但比不分层强。地铁数据一般单独一个图层字段里会有城市名和线路编号。3. 把铁路数据用起来从字段清洗到空间分析3.1 按类型拆分图层并统计里程拿到一份混合的铁路数据第一步永远是按类型拆开。拆分之后分别统计里程才能知道这份数据覆盖了多少高铁、多少普速、多少地铁。里程统计必须用投影坐标系经纬度直接算长度单位是度没有意义。import geopandas as gpd # 读取全部铁路数据 rail gpd.read_file(./rail_data/railway.gpkg, layerrailway) # 按类型拆分 hsr rail[rail[line_type] 高铁].copy() normal rail[rail[line_type] 普速].copy() metro rail[rail[line_type] 地铁].copy() # 投影到等距坐标系这里用 Web Mercator 做示例 # 全国尺度更推荐 EPSG:3857 或 Albers 等积投影 for name, gdf in [(高铁, hsr), (普速, normal), (地铁, metro)]: gdf_proj gdf.to_crs(epsg3857) total_km gdf_proj.geometry.length.sum() / 1000 print(f{name}总里程: {total_km:.1f} km, 要素数: {len(gdf)})参数说明to_crs(epsg3857)把经纬度转成 Web Mercator单位变成米geometry.length算出来的就是米除以 1000 得公里。注意 Web Mercator 在高纬度地区长度变形较大如果做全国精度要求高的统计建议用 Albers 等积投影如projaea lat_125 lat_247 lat_035 lon_0105。这一步的输出可以直接用来做数据质量校验——如果高铁里程算出来只有几千公里那大概率是数据不完整或者字段分类有问题。3.2 用空间连接把铁路和城市关联起来铁路数据的价值在于和城市、人口、经济数据关联。最常见的操作是判断哪些城市有高铁经过或者统计每个城市的地铁线路数量。空间连接spatial join是干这个的标准手段。import geopandas as gpd # 读取城市边界数据假设已有 cities gpd.read_file(./data/cities.shp) # 读取高铁数据 hsr gpd.read_file(./rail_data/railway.gpkg, layerhigh_speed_rail) # 统一坐标系 cities cities.to_crs(hsr.crs) # 空间连接判断高铁线经过哪些城市 # predicateintersects 表示线穿过城市就算 joined gpd.sjoin(hsr, cities, howinner, predicateintersects) # 统计每个城市的高铁线路数 city_hsr_count joined.groupby(city_name).size().reset_index(namehsr_count) print(city_hsr_count.sort_values(hsr_count, ascendingFalse).head(10))参数说明gpd.sjoin的predicate参数支持intersects、within、contains等铁路和城市关联一般用intersects。howinner表示只保留匹配上的记录。如果城市边界数据是面铁路是线intersects会返回所有穿过城市边界的线段一个城市可能对应多条记录所以后面要groupby聚合。这一步做完就能回答「哪些城市通了高铁」这种基础问题。3.3 地铁数据的城市内部分析地铁数据单独拿出来可以做城市内部线网密度分析。方法是用渔网fishnet把城市切成网格统计每个网格内的地铁线长度再除以网格面积得到密度。import geopandas as gpd import numpy as np from shapely.geometry import box # 读取某城市地铁数据 metro gpd.read_file(./rail_data/railway.gpkg, layermetro) metro_city metro[metro[city_name] 某市].copy() metro_city metro_city.to_crs(epsg3857) # 获取城市边界范围 minx, miny, maxx, maxy metro_city.total_bounds # 生成 1km x 1km 渔网 cell_size 1000 # 单位米 cols np.arange(minx, maxx, cell_size) rows np.arange(miny, maxy, cell_size) cells [box(x, y, x cell_size, y cell_size) for x in cols for y in rows] grid gpd.GeoDataFrame({geometry: cells}, crsEPSG:3857) # 空间叠加计算每个网格内的地铁长度 intersect gpd.overlay(grid, metro_city, howintersection) intersect[seg_len] intersect.geometry.length density intersect.groupby(intersect.index)[seg_len].sum().reset_index() density[density] density[seg_len] / (cell_size ** 2) print(density.describe())参数说明cell_size控制网格大小1km 适合城市尺度500m 适合核心区精细分析。gpd.overlay的howintersection表示只保留网格和地铁线相交的部分。density单位是 m/m²乘以 10000 可以转成 m/ha。这一步的输出可以直接用来做热力图找出地铁线网密集的区域。4. 避坑指南铁路矢量数据处理的五个常见问题4.1 解压后中文文件名乱码现象在 Linux 或 macOS 上解压 7z 包文件名显示为乱码GDAL 读取时报「文件不存在」。原因7z 打包时用了 GBK 编码而系统默认 UTF-8。解决用7z x -mcp936指定代码页解压或者用 Python 的py7zr库手动处理编码。import py7zr with py7zr.SevenZipFile(2024年全国铁路矢量数据集.7z, moder) as z: z.extractall(path./rail_data) # 如果乱码解压后手动重命名文件4.2 坐标系缺失导致叠加偏移现象两个图层叠在一起线条明显错位偏移量几百米到几公里不等。原因其中一个图层没有 .prj 文件或者 CRS 定义错误。解决先用ogrinfo确认每个图层的 CRS缺失的用set_crs()手动指定再统一转换。如果偏移量固定且在城市尺度可能是 GCJ02 和 WGS84 的差异需要用专门的转换库处理。4.3 字段类型错误导致筛选失败现象用line_type 高铁筛选结果为空。原因字段值可能有空格、全角字符或者编码问题。解决先print(df[line_type].unique())看实际值再用str.strip()去空格必要时用str.contains(高铁)做模糊匹配。# 查看实际值 print(rail[line_type].unique()) # 去空格后再筛选 rail[line_type] rail[line_type].str.strip() hsr rail[rail[line_type].str.contains(高铁, naFalse)]4.4 大数据量导致内存溢出现象读取全国铁路数据时 Python 进程被 kill或者 GeoPandas 操作极慢。原因全国尺度的线数据可能有几十万条要素全量加载到内存吃不消。解决用pyogrio或fiona的过滤功能只读需要的区域或者分块处理。# 只读取指定范围内的数据 import geopandas as gpd from shapely.geometry import box bbox box(116.0, 39.0, 117.0, 40.0) # 某区域范围 rail_sub gpd.read_file(./rail_data/railway.gpkg, bboxbbox)4.5 地铁和高铁数据混在同一图层现象做高铁分析时发现结果里混入了城市地铁线。原因数据集把所有轨道交通放在一个图层只用字段区分。解决先按字段拆分再分别处理。如果字段区分不明显可以用线路长度做辅助判断——地铁线路通常较短且集中在城市内部高铁线路跨城市且长度大。5. 进阶技巧用铁路数据做可达性分析5.1 基于站点和线路构建简易网络铁路数据的进阶用法是可达性分析。核心思路是把线路和站点转成图网络计算从某站出发到其他站的最短路径。如果没有站点数据可以用线路的端点或者等距采样点作为虚拟站点。import geopandas as gpd import networkx as nx from shapely.geometry import Point # 读取高铁线路 hsr gpd.read_file(./rail_data/railway.gpkg, layerhigh_speed_rail) hsr hsr.to_crs(epsg3857) # 构建图网络 G nx.Graph() for idx, row in hsr.iterrows(): line row.geometry # 沿线等距采样每 50km 一个虚拟节点 distances np.arange(0, line.length, 50000) points [line.interpolate(d) for d in distances] # 添加节点和边 for i in range(len(points) - 1): p1, p2 points[i], points[i 1] G.add_edge((p1.x, p1.y), (p2.x, p2.y), weight50000) print(f网络节点数: {G.number_of_nodes()}, 边数: {G.number_of_edges()}) # 计算某点到其他点的最短路径 start list(G.nodes())[0] lengths nx.single_source_dijkstra_path_length(G, start, weightweight) print(f从起点出发可达节点数: {len(lengths)})参数说明line.interpolate(d)在线段上按距离取点50000 表示每 50km 一个节点这个值可以根据分析精度调整。nx.single_source_dijkstra_path_length返回从起点到所有可达节点的最短距离。这个简易网络没有考虑实际站点和换乘但足以做趋势性分析。5.2 用等时圈展示高铁可达范围等时圈是可达性分析最直观的输出。基于上面的网络计算从某城市出发 2 小时、4 小时能到达的范围然后生成凸包或缓冲区。import geopandas as gpd from shapely.geometry import MultiPoint from shapely.ops import unary_union # 假设已有时速和最短路径结果 # 高铁平均时速按 250km/h 估算 speed_kmh 250 time_thresholds [2, 4] # 小时 for hours in time_thresholds: max_dist hours * speed_kmh * 1000 # 米 reachable [node for node, dist in lengths.items() if dist max_dist] if len(reachable) 3: continue points MultiPoint(reachable) hull points.convex_hull # 向外缓冲 30km模拟站点周边覆盖 hull_buffered hull.buffer(30000) gdf gpd.GeoDataFrame({hours: [hours], geometry: [hull_buffered]}, crsEPSG:3857) gdf.to_file(f./output/isochrone_{hours}h.gpkg, driverGPKG) print(f{hours}小时等时圈生成完成覆盖面积: {hull_buffered.area / 1e6:.0f} km²)参数说明speed_kmh是估算的平均旅行速度实际高铁旅行速度受停站影响一般按 200-250km/h 估算。buffer(30000)是给凸包外扩 30km因为凸包只连接最远点会漏掉边缘区域。输出为 GeoPackage 格式可以直接在 GIS 软件里叠加底图查看。5.3 几个让结果更可信的细节第一网络构建时要把地铁和普速铁路也加进去否则可达性只反映高铁覆盖不反映实际出行。第二等时圈的凸包方法在站点稀疏区域会严重高估覆盖范围更严谨的做法是用实际路网做缓冲区。第三如果数据里有开通年份字段可以按年份做时间序列分析看高铁网络如何逐年扩张。我一般会先用 2024 年数据做现状分析再用历史年份数据做对比这样出来的图更有说服力。最后说一个血泪经验铁路矢量数据的几何精度参差不齐有些线路是简化过的直接用来算长度会偏短。如果做里程统计最好先用simplify()的逆操作——检查几何节点密度节点太稀的线路要标记出来必要时用官方里程数据做校正。这个坑我在第一次做全国高铁里程统计时踩过算出来比官方数据少了近两成后来发现是数据简化导致的。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站