将networkx边缘属性/权重分配给dict

时间:2015-01-23 10:34:41

标签: python networkx

我运行这个程序:

import networkx as nx
from pylab import *
g=nx.Graph()

g.add_edge('a','b', weight=3)

g.add_edge('a','c', weight=2)

g.add_edge('b','c', weight=7)

w=nx.get_edge_attributes(g, 'weight')

w[('b','a')]=3

w[('c','a')]=2

w[('c','b')]=7

我不明白为什么w dict只包含5个而不是6个项目:

{('b', 'a'): 3, ('c', 'a'): 2, ('a', 'b'): 3, ('c', 'b'): 7, ('a', 'c'): 2}

('b','c')条目已消失......

我在这里做错了什么?

2 个答案:

答案 0 :(得分:2)

您的图表不是定向的。这是问题的根本原因。

运行代码的第一部分时:

import networkx as nx
from pylab import *
g=nx.Graph()

g.add_edge('a','b', weight=3)

g.add_edge('a','c', weight=2)

g.add_edge('b','c', weight=7)

w=nx.get_edge_attributes(g, 'weight')

w放入dict中,每个dict的键都是其中一个边。但是边缘内的节点顺序并不重要。所以,让我们看一下w

w
> {('a', 'b'): 3, ('a', 'c'): 2, ('c', 'b'): 7}

注意---您为('b', 'c')定义了边缘权重。但是在w中,它与密钥('c','b')一起存储。

所以稍后,当你定义w[('c','b')]时,你会覆盖它。其他边缘没有发生这种情况,因为随机偶然发生的网络碰巧按照你预期的顺序返回它们。

我认为您正在尝试定义w,以便无论您检查的边缘顺序如何,您的权重都相同。

最好使用内置的networkx命令来获取权重而不要使用w

g.get_edge_data('a','b')['weight']

但是,如果你真的想要w,那么一种方法是循环使用w的键作为

for edge in w:
    w[([edge[1],edge[0])] = w[edge]

或者您可以定义一个函数

def f(edge,w):
    if edge in w:
        return w[edge]
    else:
        return w[(edge[1],edge[0])

对正在发生的事情进行更多解释:

你不能假设networkx会以与给定它们相同的顺序返回无向图的边缘。它是一个无向图,所以任何假定边缘隐含方向的东西都会遇到麻烦。

基本上这是因为networkx将节点存储在字典结构中。因此,您不能假设它以任何顺序返回节点。因此,特别是在networkx寻找其边缘的情况下,它以某种顺序通过节点。在这种情况下,它会在到达'c'之前到达'b'。所以它首先获得了c的优势。当它到达b时,它知道它已经有了这个边缘,所以它就会把它留下来。

答案 1 :(得分:1)

我发现了(经过一些尝试并查看了get_edge_attribute的代码)。在此方法本身中,边缘在此处被检索:

if G.is_multigraph():
        edges = G.edges(keys=True, data=True)
    else:
        edges = G.edges(data=True)
    return dict( (x[:-1], x[-1][name]) for x in edges if name in x[-1] )

在您的情况下,图表不是多图。所以它根据G.edges()返回的列表构建字典。所以我用以下代码做了一点测试:

g.add_edge('a','b', weight=3)

print "edges after adding 'ab':  " + str(g.edges(data=True))

g.add_edge('a','c', weight=2)

print "edges after adding 'ac':  " + str(g.edges(data=True))

g.add_edge('b','c', weight=7)

print "edges after adding 'bc':  " + str(g.edges(data=True))

输出:

edges after adding 'ab':  [('a', 'b', {'weight': 3})]
edges after adding 'ac':  [('a', 'c', {'weight': 2}), ('a', 'b', {'weight': 3})]
edges after adding 'bc':  [('a', 'c', {'weight': 2}), ('a', 'b', {'weight': 3}), ('c', 'b', {'weight': 7})]

查看输出中的最后一行:我们添加了边缘' bc'不是' cb',但在边缘列表中,没有'''边缘,而不是有一个' cb'边缘。这就是为什么你没有看到边缘' bc'因为它不存在。

我不知道确切的原因,为什么会这样做。