我想执行一些边缘操作:有边缘并增加边缘权重。
我试过了:
from igraph import *
g = Nexus.get("karate")
if g.es.select(_from=0, _target=1):
g.es.select(_from=0, _target=1)['weight'] += 1
else:
g.add_edge(0, 1, weight=1)
我遇到问题:增加运营商:
g.es.select(_from=0, _target=1)['weight'] += 1 # not work
然而,当进程添加新的边缘权重时,这不起作用。 E.g:
g.es.select(_from=0, _target=1)['weight'] = 200000 # this is ok
另外,我想要一些更高效或更优雅的东西。例如,在库IGRAPH中执行此操作的操作/函数在计算上更有效吗?
答案 0 :(得分:3)
好的,你应该知道一些事情,以了解为什么增加操作不起作用。
首先,g.es.select()
返回EdgeSeq
个对象,即边缘序列。在您的情况下,如果边存在,则返回长度为1的边序列,否则返回长度为零的边序列:
>>> edges = g.es.select(_from=0, _to=1)
>>> edges
<igraph.EdgeSeq at 0x10ce62350>
>>> len(edges)
1
其次,在['weight']
上使用EdgeSeq
操作会返回列表,其中包含EdgeSeq
中每条边的权重属性:
>>> edges["weight"]
[42]
第三,x += 1
基本上等同于x = x + 1
,因此当您尝试使用+=
增加权重时,您尝试将追加 1添加到列表中相反(因为x
是一个列表,请参阅我的第二点),这将无效,因为您只能将另一个列表附加到列表中。此外,您获得的列表只是边缘属性的副本,因此修改它不会改变边缘属性:
>>> edges["weight"] += 1
TypeError: 'int' object is not iterable
>>> edges["weight"] += [1]
>>> edges["weight"]
[42]
最简单的解决方案是从Edge
获取单个EdgeSeq
对象并对其进行修改,因为在['weight']
上使用Edge
操作会将权重返回为单个元素,您可以使用+=
运算符以简洁的方式增加并写回边缘:
>>> edge = edges[0]
>>> edge
igraph.Edge(<igraph.Graph object at 0x10d788148>, 0, {'weight': 42})
>>> edge["weight"] += 1
>>> edge
igraph.Edge(<igraph.Graph object at 0x10d788148>, 0, {'weight': 43})
但是,在这种情况下我会避免使用g.es.select
,因为它会评估g.es
中的每个边缘,以便找到符合条件的边缘。而不是那样,我会使用g.get_eid()
来获取我正在寻找的边缘的ID,然后使用g.es[edge_id]
来找到合适的边缘:
eid = g.get_eid(0, 1, error=False)
if eid >= 0:
g.es[eid]["weight"] += 1
else:
g.add_edge(0, 1, weight=1)
另一种方法是识别igraph对象可以被视为邻接矩阵。当图形具有名为weight
的边缘属性时,调用g[source, target]
将返回给定源顶点和目标顶点之间边缘的权重,这也可用于设置当然的权重。当图表没有名为weight
的边缘属性时,如果g[source, target]
和source
连接,target
只是1,否则为零。所以,你也可以这样做:
g = Nexus.get('karate')
g.es["weight"] = 1 # to ensure that existing edges have weight=1
g[0,1] += 1
答案 1 :(得分:1)
仅适用于工作,(既不高效又不优雅)
>>> from igraph import *
>>> g = Nexus.get('karate')
>>> print g.es.select(_from=0, _target=1)['weight'] # to see the value
[4.0]
>>> if g.es.select(_from=0, _target=1):
... buff = g.es.select(_from=0, _target=1)['weight']
... buff[0] += 1
... g.es.select(_from=0, _target=1)['weight'] = buff
... else:
... g.add_edge(0, 1, weight=1)
>>> print g.es.select(_from=0, _target=1)['weight'] # to see the value
[5.0]
答案 2 :(得分:0)
我强烈推荐使用networkx。这是相同的代码。
import networkx as nx
G = nx.karate_club_graph()
#you can assign all with a starting weight
for x,y in G.edges_iter():
G.add_edge(x,y,weight=1)
# then add more as you come across them.
for x,y in SomeIterableAffectingTheGraph:
G.edge[x][y]['weight']+=1