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

如何从OSMnx图中筛选指定边并构建子图?

问题:如何用OSMnx筛选目标边并生成子图?

问题背景

  • 下载OSM地图为shapefile格式,筛选出目标路线的节点与特定街道边,导出为CSV后导入Python Notebook
  • 通过G.subgraph(nodes)成功生成仅包含目标节点的子图,但无法筛选目标边
  • 尝试使用G.edge_subgraph(edges),分别传入OSM ID列表[osmid_0,...,osmid_i]和节点对列表[(u_0,v_0),...(u_i,v_i)],执行G_mh.edge_subgraph(roads['osmid'])时触发以下错误:
Output exceeds the size limit. Open the full output data in a text editor---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[230], line 1
----> 1 G_mh.edge_subgraph(roads['osmid'])

File ~/Library/Python/3.9/lib/python/site-packages/networkx/classes/graph.py:1865, in Graph.edge_subgraph(self, edges)
   1827 def edge_subgraph(self, edges):
   1828     """Returns the subgraph induced by the specified edges.
   1829 
   1830     The induced subgraph contains each edge in `edges` and each
   (...)
   1863 
   1864     """
-> 1865     return nx.edge_subgraph(self, edges)

File ~/Library/Python/3.9/lib/python/site-packages/networkx/classes/function.py:445, in edge_subgraph(G, edges)
    443 if G.is_multigraph():
    444     if G.is_directed():
-> 445         induced_edges = nxf.show_multidiedges(edges)
    446     else:
    447         induced_edges = nxf.show_multiedges(edges)

File ~/Library/Python/3.9/lib/python/site-packages/networkx/classes/filters.py:69, in show_multidiedges(edges)
     68 def show_multidiedges(edges):
---> 69     edges = {(u, v, k) for u, v, k in edges}
...
     68 def show_multidiedges(edges):
---> 69     edges = {(u, v, k) for u, v, k in edges}
     70     return lambda u, v, k: (u, v, k) in edges

ValueError: too many values to unpack (expected 3)

解决方案

错误原因

OSMnx默认生成的是MultiDiGraph(多有向图),edge_subgraph对这类图要求传入**(u, v, key)**三元组作为边的唯一标识符,而不是单独的osmid或(u,v)二元组。另外,osmid是边的属性字段,不是图的边标识符,直接传入osmid列表会触发解包错误。

具体实现步骤

  1. 通过osmid筛选边并生成子图
    从CSV中提取目标osmid,遍历原图匹配对应边的三元组:

    import osmnx as ox
    import pandas as pd
    
    # 假设roads是导入的CSV数据框,包含目标边的osmid列
    target_osmids = set(roads['osmid'])
    
    # 遍历原图的所有边,收集符合条件的(u, v, key)三元组
    selected_edges = []
    for u, v, key, edge_data in G_mh.edges(data=True, keys=True):
        # 注意部分边的osmid可能是列表(如合并的路段),需特殊处理
        edge_osmid = edge_data.get('osmid')
        if isinstance(edge_osmid, list):
            if any(oid in target_osmids for oid in edge_osmid):
                selected_edges.append((u, v, key))
        else:
            if edge_osmid in target_osmids:
                selected_edges.append((u, v, key))
    
    # 生成边诱导子图
    G_sub = G_mh.edge_subgraph(selected_edges)
    
  2. 结合节点ID与osmid精准匹配
    如果CSV中包含图的节点ID(u和v列),可以更精准地定位边:

    selected_edges = []
    for _, row in roads.iterrows():
        u, v, target_oid = row['u'], row['v'], row['osmid']
        # 遍历该(u,v)对应的所有key(多图特性)
        if u in G_mh and v in G_mh[u]:
            for key in G_mh[u][v]:
                edge_data = G_mh[u][v][key]
                edge_osmid = edge_data.get('osmid')
                # 处理osmid为列表的情况
                match = False
                if isinstance(edge_osmid, list):
                    match = target_oid in edge_osmid
                else:
                    match = (edge_osmid == target_oid)
                if match:
                    selected_edges.append((u, v, key))
                    break  # 找到匹配项后退出循环
    G_sub = G_mh.edge_subgraph(selected_edges)
    
  3. 保存子图
    生成子图后,可通过以下方式保存:

    # 保存为GraphML格式(保留所有属性,推荐)
    ox.save_graphml(G_sub, filepath='target_subgraph.graphml')
    
    # 保存为shapefile(适合GIS工具处理)
    ox.save_graph_shapefile(G_sub, filepath='target_subgraph')
    

内容的提问来源于stack exchange,提问作者sdb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:05:07