【问题标题】:How to add edge length as a weight in betweeness centrality using OSMNx/Networkx?如何使用 OSMNx/Networkx 在中间中心性中添加边长作为权重?
【发布时间】:2019-05-07 18:39:32
【问题描述】:

我正在使用 Python 库 OSMNx 来获取给定街道网络 G 的中介中心性。从我所见,模块 osmnx.stats.extended_stats(G, bc=True) 使用 NetworkX 模块 networkx.betweenness_centrality(G, normalized=True, weight=None) 将所有边权重设置为相等来计算中介。由于边长已经嵌入到 G 中,因此可以直接将其用作权重。我仍然无法找到一种方法来做到这一点。

如何使用这两个库将权重设置为 1/length?

请考虑以下示例给出的图表

import osmnx as ox
import networkx as nx

#Using OSMNx
G = ox.graph_from_bbox(37.79, 37.78, -122.41, -122.43, network_type='drive')
stats = ox.extended_stats(G,bc=True)
bet1 = stats["betweenness_centrality"]

#Using NetworkX
bet2 = nx.betweenness_centrality(G, weight=None)

这是我迄今为止尝试过的:

import pandas as pd

l = nx.get_edge_attributes(G, 'length')
l = pd.Series(l).to_frame()
w=1/l
w = w.to_dict(orient="index")
nx.set_edge_attributes(G, w, 'w')
bet3 = nx.betweenness_centrality(G, weight='w')

但我得到的结果与不使用权重完全相同。

【问题讨论】:

  • 你看过边缘数据了吗?例如 g.edges(data=True)?
  • 是的,我有。与每条边相关的数据都在那里,可以用作权重。但是,据我所见,设置 weight=Noneweight='length'weight='w'(w=1/length)返回相同的输出。

标签: python openstreetmap networkx


【解决方案1】:

您在最短路径算法中检测到networkx 处理MultiDiGraph 的错误。请参见以下示例:

import networkx as nx

graph = nx.Graph()
graph.add_weighted_edges_from([(1,2,1), (2,3,2), (1,3,1)])
print(nx.betweenness_centrality(graph))
# {1: 0.0, 2: 0.0, 3: 0.0}
print(nx.betweenness_centrality(graph, weight="weight"))
# {1: 0.5, 2: 0.0, 3: 0.0}


multi_di_graph = nx.MultiDiGraph()
multi_di_graph.add_weighted_edges_from([(1,2,1), (2,3,2), (1,3,1)])
print(nx.betweenness_centrality(multi_di_graph))
# {1: 0.0, 2: 0.0, 3: 0.0}
print(nx.betweenness_centrality(multi_di_graph, weight="weight"))
# {1: 0.0, 2: 0.0, 3: 0.0}

错误在 _single_source_dijkstra_path_basic 尤其是下面code lines

for w, edgedata in G[v].items():
    vw_dist = dist + edgedata.get(weight, 1)

我不确定networkx 中的最短路径算法是否适用于多图,但由于我没有发现任何注释,我认为这是一个错误。 我建议您在networkx GitHub 上打开一个问题。 如果相关部分可能,您也可以考虑转换为通常的DiGraph

【讨论】:

  • 感谢您富有洞察力的回答和清晰的示例。我按照您的建议部分解决了我的问题,将MultiDiGraph 转换为GraphDigraph(我仍在查看这两者的结果差异)。我还在NetworkX GitHub开了一个新问题。
  • 似乎他们想为 2.4 版本解决这个问题。在此之前,您可以创建一个具有两个节点之间所有边的最小边权重的有向图。 DiGraph 和 Graph 之间的差异将在所有节点对上,其中仅存在一条边或权重不同。支持和/或接受答案会很棒;)
【解决方案2】:

模块 osmnx.stats.extended_stats(G, bc=True) 使用 NetworkX 模块 networkx.betweenness_centrality(G, normalized=True, weight=None) 将所有边权重设置为相等来计算介数。由于边长已经嵌入到 G 中,因此可以直接将其用作权重。

OSMnx automatically uses edge lengths 作为计算中介中心性时的权重。对于任何进一步的自定义,您可以直接在您的 OSMnx 图形对象上调用 nx.betweenness_centrality(G),并根据需要对其进行参数化。

【讨论】:

  • 亲爱的 Geoff 感谢您的及时回复,并祝贺您收到了令人惊叹的包裹!我仍然对如何计算介数感到有些困惑。按照我之前的示例,一旦从 OSMnx ox.extended_stats(G,bc=True) 检索到 G,nx.betweenness_centrality(G, weight=None)nx.betweenness_centrality(G, weight='length') 就会提供完全相同的结果。这就是为什么我假设 OSMnx 不使用边长作为权重。
  • @gboeing:根据我上面的测试,由于您使用的是MultiDiGraph 的实例,OSMNx 中的调用是正确的,但networkx 将返回没有任何权重的结果。请参阅我的答案中的示例。
  • 是的,看起来应该在 networkx 的 github 问题上打开上游错误报告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 2020-04-28
  • 2015-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多