如何基于OSMNX获取的数据构建邻接矩阵与度矩阵?
基于OSMNX路网构建邻接矩阵与度矩阵的思路
我来帮你梳理具体的实现思路和代码,结合你给出的路网数据获取代码,分步骤来:
一、前置准备
先运行你的代码拿到路网数据,同时导入需要的依赖库:
import osmnx as ox import numpy as np import networkx as nx # 获取指定区域的驾驶路网 G = ox.graph_from_bbox(37.79, 37.78, -122.41, -122.43, network_type='drive') nodes, edges = ox.graph_to_gdfs(G)
二、构建邻接矩阵
邻接矩阵用于表示节点间的连接关系,针对驾驶路网(有向图),我们通常会构建有向二进制邻接矩阵(仅标记是否相连)或加权邻接矩阵(比如用道路长度作为权重)。
方法1:基于GeoDataFrame手动构建
OSM的节点ID(osmid)是离散值,第一步需要把它映射为连续的整数索引,避免矩阵出现大量空行空列:
# 获取所有节点的osmid列表 node_osm_ids = nodes.index.values # 构建映射字典:osmid → 矩阵索引 osmid_to_idx = {osmid: idx for idx, osmid in enumerate(node_osm_ids)} num_nodes = len(node_osm_ids)
构建有向二进制邻接矩阵
# 初始化全零矩阵 adj_matrix = np.zeros((num_nodes, num_nodes), dtype=int) # 遍历每条边填充矩阵 for _, edge in edges.iterrows(): u_idx = osmid_to_idx[edge['u']] v_idx = osmid_to_idx[edge['v']] # 标记起点u到终点v存在连接 adj_matrix[u_idx][v_idx] = 1
构建加权邻接矩阵(以道路长度为权重)
adj_matrix_weighted = np.zeros((num_nodes, num_nodes), dtype=np.float64) for _, edge in edges.iterrows(): u_idx = osmid_to_idx[edge['u']] v_idx = osmid_to_idx[edge['v']] # 用道路长度作为权重值 adj_matrix_weighted[u_idx][v_idx] = edge['length']
方法2:直接用NetworkX内置方法(更高效)
OSMNX返回的G本身就是NetworkX的有向图对象,直接调用内置方法可以快速生成矩阵:
# 生成二进制邻接矩阵(nodelist保证节点顺序和我们的映射一致) adj_matrix_nx = nx.to_numpy_array(G, nodelist=node_osm_ids, dtype=int) # 生成加权邻接矩阵(指定用length作为权重) adj_matrix_weighted_nx = nx.to_numpy_array(G, nodelist=node_osm_ids, weight='length')
三、构建度矩阵
度矩阵是对角矩阵,对角线元素对应节点的度:有向图需区分入度(指向该节点的边数)和出度(从该节点出发的边数),无向图则只需单一的度值。
方法1:从邻接矩阵推导
# 有向图:出度矩阵(行求和) out_degree = np.sum(adj_matrix, axis=1) out_degree_matrix = np.diag(out_degree) # 有向图:入度矩阵(列求和) in_degree = np.sum(adj_matrix, axis=0) in_degree_matrix = np.diag(in_degree) # 无向图:先转无向图再计算度 G_undirected = G.to_undirected() adj_matrix_undir = nx.to_numpy_array(G_undirected, nodelist=node_osm_ids) undir_degree = np.sum(adj_matrix_undir, axis=1) undir_degree_matrix = np.diag(undir_degree)
方法2:直接用NetworkX内置方法
# 出度矩阵 out_degree_list = [d for _, d in nx.out_degree(G, nodelist=node_osm_ids)] out_degree_matrix_nx = np.diag(out_degree_list) # 入度矩阵 in_degree_list = [d for _, d in nx.in_degree(G, nodelist=node_osm_ids)] in_degree_matrix_nx = np.diag(in_degree_list) # 无向图度矩阵 undir_degree_list = [d for _, d in nx.degree(G_undirected, nodelist=node_osm_ids)] undir_degree_matrix_nx = np.diag(undir_degree_list)
小提示
- 记得保留
osmid_to_idx映射字典,后续可以把矩阵索引转回osmid,匹配nodes中的经纬度等空间属性。 - 大规模路网建议用NetworkX内置方法,底层做了性能优化,运行效率更高。
内容的提问来源于stack exchange,提问作者Kyv
相关产品推荐
相关产品推荐

