如何基于OpenStreetMap的way_id而非地理位置绘制道路并按count着色?
问题描述
我有一个包含way_id、longitude、latitude、count列的数据集,其中way_id对应OpenStreetMap的道路(比如way_id=3997428对应OSM上的某条道路)。目前我用plotly.express.scatter_mapbox只能绘制定位点,没法画出实际道路。我想在Python中绘制所有way_id对应的道路,并且根据count列自定义道路颜色。查过OSMnx和OSM文档,只找到适用于图的osmnx.plot_graph_route方法,没找到合适方案,求解决办法。
数据样本
longitude latitude count way_id 3996189 -3.732425 40.362795 12173 3996191 -3.596423 40.429618 1656 3996195 -3.603010 40.429786 211 3996196 -3.605451 40.434605 772 3996199 -3.606216 40.434230 1063 3996203 -3.606369 40.434044 40 3997425 -3.606917 40.424344 3080 3997426 -3.607961 40.434094 2095 3997427 -3.604154 40.423951 465 3997428 -3.606116 40.425008 217
复现DataFrame代码
import pandas as pd df = pd.DataFrame({'longitude': {3996189: -3.732425, 3996191: -3.596423, 3996195: -3.60301, 3996196: -3.605451, 3996199: -3.606216, 3996203: -3.606369, 3997425: -3.606917, 3997426: -3.607961, 3997427: -3.604154, 3997428: -3.606116}, 'latitude': {3996189: 40.362795, 3996191: 40.429618, 3996195: 40.429786, 3996196: 40.434605, 3996199: 40.43423, 3996203: 40.434044, 3997425: 40.424344, 3997426: 40.434094, 3997427: 40.423951, 3997428: 40.425008}, 'count': {3996189: 12173, 3996191: 1656, 3996195: 211, 3996196: 772, 3996199: 1063, 3996203: 40, 3997425: 3080, 3997426: 2095, 3997427: 465, 3997428: 217}})
当前绘制点位的代码
import plotly.express as px from plotly import plot fig = px.scatter_mapbox(df, lat="latitude", lon="longitude", color="count", zoom=10, mapbox_style='carto-positron', size="count") plot(fig, auto_open=True)
解决方案
核心思路:用OSMnx批量获取每个way_id对应的道路几何数据,再结合Plotly的Mapbox绘制路径,同时根据count值映射颜色。
步骤1:安装依赖
确保安装所需库:
pip install osmnx plotly pandas
步骤2:批量获取道路几何数据
遍历每个way_id,提取道路的节点坐标:
import osmnx as ox import pandas as pd # 获取单条道路的经纬度坐标列表 def get_way_coords(way_id): try: way_gdf = ox.geocode_to_gdf(f"way/{way_id}") # 提取LineString类型的道路坐标 coords = way_gdf.iloc[0]['geometry'].coords return [[lon, lat] for lon, lat in coords] except Exception as e: print(f"获取way {way_id} 失败: {e}") return None # 为每个way_id匹配道路坐标 df['coords'] = df.index.map(get_way_coords) # 过滤获取失败的记录 df = df.dropna(subset=['coords'])
步骤3:用Plotly绘制带颜色的道路
根据count值生成渐变颜色,逐条绘制道路:
import plotly.graph_objects as go from plotly.colors import scale_colors # 生成count对应的渐变颜色(用viridis配色,可替换为plasma/cividis等) count_min, count_max = df['count'].min(), df['count'].max() colors = scale_colors('viridis', df['count'].values, count_min, count_max) # 初始化地图 fig = go.Figure() # 逐条添加道路轨迹 for idx, row in df.iterrows(): lons, lats = zip(*row['coords']) fig.add_trace(go.Scattermapbox( lon=lons, lat=lats, mode='lines', line=dict(width=3, color=colors[idx]), name=f"Way {idx} (count: {row['count']})" )) # 设置地图布局 fig.update_layout( mapbox_style='carto-positron', mapbox_zoom=10, mapbox_center={"lat": df['latitude'].mean(), "lon": df['longitude'].mean()}, showlegend=True, title="OSM道路按count值着色" ) # 显示图表 fig.show()
关键说明
- OSMnx的
geocode_to_gdf可直接通过way/{way_id}获取道路的几何数据,返回的GeoDataFrame包含LineString类型的道路形状信息。 - Plotly的
Scattermapbox通过mode='lines'绘制路径,line.color绑定自定义颜色实现按count值着色。 - 配色方案可根据需求替换,也可使用
plotly.colors.make_colorscale自定义颜色范围。
内容的提问来源于stack exchange,提问作者sander
相关产品推荐
相关产品推荐

