You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 05:25:37