从《交通时空大数据分析》到实战:用transbigdata和geopandas处理上海地铁数据的完整流程
从理论到实践用Python处理上海地铁数据的全流程解析当你翻开《交通时空大数据分析》这类专业书籍时是否曾被那些抽象的概念和公式困扰交通网络拓扑、站点序列分析、客流模拟...这些听起来高大上的术语其实都可以通过Python工具链转化为实实在在的代码操作。本文将带你完整走一遍从数据获取到分析可视化的全流程使用transbigdata和geopandas这两个强大的Python库把书本知识变成可执行的解决方案。1. 环境准备与数据获取1.1 搭建分析环境在开始之前我们需要配置合适的Python环境。推荐使用Anaconda创建独立环境conda create -n transit_analysis python3.9 conda activate transit_analysis pip install geopandas transbigdata requests shapely注意geopandas在Windows系统上安装可能较复杂建议通过conda安装基础依赖1.2 获取地铁网络数据上海地铁数据可以通过高德地图API获取。以下代码展示了如何安全地请求数据并处理响应import requests import json def fetch_subway_data(): url https://map.amap.com/service/subway params {_: 1707368894338, srhdata: 3100_drw_shanghai.json} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } try: response requests.get(url, paramsparams, headersheaders) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f数据获取失败: {e}) return None这个函数会返回包含上海地铁所有线路和站点信息的JSON数据。相比书本上的静态数据直接从API获取的信息更加实时准确。2. 数据清洗与结构化处理2.1 解析原始数据获取的原始数据需要转换为更易分析的格式。我们首先将站点信息提取为结构化DataFrameimport pandas as pd from shapely.geometry import Point def parse_station_data(raw_data): stations [] for line in raw_data[l]: line_name line[kn] start_station line[st][0][n] end_station line[st][-1][n] for idx, station in enumerate(line[st], 1): coords station[sl].split(,) stations.append({ line_name: line_name, station_name: station[n], longitude: float(coords[0]), latitude: float(coords[1]), sequence: idx, direction: f{start_station}→{end_station} }) return pd.DataFrame(stations)2.2 数据质量检查处理后的数据需要进行验证重复站点检查同一线路上的站点名称是否唯一坐标范围验证确保所有站点位于合理的经纬度范围内线路完整性检查每条线路是否有起点和终点def validate_data(df): # 检查重复站点 dup_stations df.duplicated(subset[line_name, station_name], keepFalse) if dup_stations.any(): print(发现重复站点:, df[dup_stations][station_name].unique()) # 检查坐标范围上海大致经纬度范围 valid_lon (120.8, 122.2) valid_lat (30.7, 31.8) outliers df[ (df[longitude] valid_lon[0]) | (df[longitude] valid_lon[1]) | (df[latitude] valid_lat[0]) | (df[latitude] valid_lat[1]) ] if not outliers.empty: print(坐标异常站点:, outliers[[station_name, longitude, latitude]])3. 高级空间分析技术3.1 使用transbigdata进行交通网络分析transbigdata是专为交通大数据设计的Python库提供了丰富的分析方法import transbigdata as tbd import geopandas as gpd def analyze_network(stations_df): # 转换为GeoDataFrame geometry [Point(xy) for xy in zip(stations_df[longitude], stations_df[latitude])] gdf gpd.GeoDataFrame(stations_df, geometrygeometry, crsEPSG:4326) # 计算站点间距矩阵 distance_matrix tbd.distance_matrix(gdf) # 识别换乘站 transfer_stations tbd.identify_transfer_stations(gdf, col[line_name, station_name]) return distance_matrix, transfer_stations3.2 构建地铁网络拓扑地铁网络的拓扑结构是许多高级分析的基础。我们可以用NetworkX构建图结构import networkx as nx def build_network_graph(stations_df): G nx.Graph() # 添加节点 for _, row in stations_df.iterrows(): G.add_node(row[station_name], pos(row[longitude], row[latitude]), linerow[line_name]) # 添加边同一线路相邻站点 for line in stations_df[line_name].unique(): line_stations stations_df[stations_df[line_name] line] line_stations line_stations.sort_values(sequence) for i in range(len(line_stations)-1): station1 line_stations.iloc[i][station_name] station2 line_stations.iloc[i1][station_name] G.add_edge(station1, station2, lineline) return G4. 可视化与成果输出4.1 基础地图可视化使用geopandas和matplotlib可以创建专业级的交通网络地图import matplotlib.pyplot as plt def plot_network(gdf): fig, ax plt.subplots(figsize(12, 10)) # 绘制线路 for line in gdf[line_name].unique(): line_data gdf[gdf[line_name] line] ax.plot(line_data[longitude], line_data[latitude], labelline, linewidth2) # 绘制站点 ax.scatter(gdf[longitude], gdf[latitude], colorblack, s20) # 标注换乘站 transfer_stations gdf[station_name].value_counts() transfer_stations transfer_stations[transfer_stations 1].index for station in transfer_stations: station_data gdf[gdf[station_name] station].iloc[0] ax.text(station_data[longitude], station_data[latitude], station, fontsize8, hacenter, vabottom) ax.legend() plt.title(上海地铁网络) plt.xlabel(经度) plt.ylabel(纬度) plt.grid(True) plt.tight_layout() return fig4.2 交互式可视化对于更丰富的探索可以使用folium创建交互地图import folium def create_interactive_map(gdf): # 计算地图中心点 avg_lat gdf[latitude].mean() avg_lon gdf[longitude].mean() m folium.Map(location[avg_lat, avg_lon], zoom_start12) # 添加线路 for line in gdf[line_name].unique(): line_data gdf[gdf[line_name] line] locations line_data[[latitude, longitude]].values.tolist() folium.PolyLine(locations, colorblue, weight2.5, opacity1).add_to(m) # 添加站点标记 for _, row in gdf.iterrows(): folium.CircleMarker( location[row[latitude], row[longitude]], radius3, popupf{row[station_name]} ({row[line_name]}), colorred, fillTrue ).add_to(m) return m5. 进阶分析应用5.1 客流模拟基础基于地铁网络我们可以构建简单的客流模拟模型def simulate_passenger_flow(network_graph, transfer_stations, num_passengers1000): results [] all_stations list(network_graph.nodes()) for _ in range(num_passengers): # 随机选择起点和终点 origin np.random.choice(all_stations) destination np.random.choice(all_stations) # 计算最短路径 try: path nx.shortest_path(network_graph, origin, destination) travel_time len(path) * 2 # 假设每站2分钟 # 记录换乘次数 transfers 0 for i in range(1, len(path)-1): prev_lines network_graph.nodes[path[i-1]][line] curr_lines network_graph.nodes[path[i]][line] next_lines network_graph.nodes[path[i1]][line] if isinstance(prev_lines, str): prev_lines [prev_lines] if isinstance(curr_lines, str): curr_lines [curr_lines] if isinstance(next_lines, str): next_lines [next_lines] # 判断是否换乘 if not set(prev_lines) set(next_lines): transfers 1 results.append({ origin: origin, destination: destination, path_length: len(path), travel_time: travel_time, transfers: transfers }) except nx.NetworkXNoPath: continue return pd.DataFrame(results)5.2 网络性能指标计算评估地铁网络的几个关键指标def calculate_network_metrics(network_graph): metrics {} # 平均最短路径长度 metrics[avg_shortest_path] nx.average_shortest_path_length(network_graph) # 网络直径 metrics[diameter] nx.diameter(network_graph) # 聚类系数 metrics[clustering] nx.average_clustering(network_graph) # 中心性分析 degree_centrality nx.degree_centrality(network_graph) metrics[most_central_station] max(degree_centrality, keydegree_centrality.get) return metrics6. 工程实践建议在实际项目中处理城市交通数据时有几个经验值得分享数据更新机制地铁网络经常变化建议设置定期自动更新数据的流程而不是依赖一次性抓取。可以编写脚本每周检查数据变化。性能优化当处理大规模交通数据时GeoPandas操作可能变慢。对于包含历史数据的分析考虑使用Dask或PySpark进行分布式计算。坐标系统一致性确保所有地理数据使用相同的坐标参考系统(CRS)。上海市区地图通常使用EPSG:4547或EPSG:3857而不是默认的WGS84(EPSG:4326)。异常数据处理实际数据中经常会出现坐标漂移、站点命名不一致等问题。建立健壮的数据清洗流程比想象中更重要。可视化优化当线路密集时基础可视化可能变得混乱。可以考虑按线路分层显示使用3D可视化展示不同线路的高度添加时间维度制作动态变化图