组合(加入)networkx Graphs
Posted
技术标签:
【中文标题】组合(加入)networkx Graphs【英文标题】:Combine (join) networkx Graphs 【发布时间】:2015-12-15 14:39:28 【问题描述】:假设我有两个 networkx 图,G
和 H
:
G=nx.Graph()
fromnodes=[0,1,1,1,1,1,2]
tonodes=[1,2,3,4,5,6,7]
for x,y in zip(fromnodes,tonodes):
G.add_edge(x,y)
H=nx.Graph()
fromnodes=range(2,8)
tonodes=range(8,14)
for x,y in zip(fromnodes,tonodes):
H.add_edge(x,y)
加入两个networkx图的最佳方法是什么?
我想保留节点名称(注意公共节点,2 到 7)。当我使用nx.disjoint_union(G,H)
时,并没有发生这种情况:
>>> G.nodes()
[0, 1, 2, 3, 4, 5, 6, 7]
>>> H.nodes()
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
>>> Un= nx.disjoint_union(G,H)
>>> Un.nodes()
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
#
H
节点标签已更改(不是我想要的)。我想在具有相同编号的节点处加入图表。
注意。这不是Combine two weighted graphs in NetworkX的重复项@
【问题讨论】:
如果两者都存在边,你想做什么?它应该成为双刃剑吗?还是只有一条边? @Joel 嗯我对这两种情况都感兴趣。让我们说单边。 您编写的代码可以很好地处理单一边缘情况。你刚刚做的多边案例U=nx.MultiGraph()
还有一个简化的例子:for x,y in zip(fromnodes,tonodes): G.add_edge(x,y)
可以写成G.add_edges_from(zip(fromnodes,tonodes))
【参考方案1】:
如果你想将图 H 添加到 G 然后返回 G,你可以使用update 方法。
【讨论】:
【参考方案2】:您要查找的函数是compose,它会生成一个图,其中包含两个图中的所有边和所有节点。如果两个图都有一个同名的节点,那么一个副本最终会出现在新图中。同样,如果两者都存在相同的边缘。这是一个示例,包括边缘/节点属性:
import networkx as nx
G=nx.Graph()
G.add_node(1, weight = 2)
G.add_node(2, weight = 3)
G.add_edge(1,2, flux = 5)
G.add_edge(2,4)
H=nx.Graph()
H.add_node(1, weight = 4)
H.add_edge(1,2, flux = 10)
H.add_edge(1,3)
F = nx.compose(G,H)
#F has all nodes & edges of both graphs, including attributes
#Where the attributes conflict, it uses the attributes of H.
G.nodes(data=True)
> NodeDataView(1: 'weight': 2, 2: 'weight': 3, 4: )
H.nodes(data=True)
> NodeDataView(1: 'weight': 4, 2: , 3: )
F.nodes(data=True)
> NodeDataView(1: 'weight': 4, 2: 'weight': 3, 4: , 3: )
G.edges(data=True)
> EdgeDataView([(1, 2, 'flux': 5), (2, 4, )])
H.edges(data=True)
> EdgeDataView([(1, 2, 'flux': 10), (1, 3, )])
F.edges(data=True)
EdgeDataView([(1, 2, 'flux': 10), (1, 3, ), (2, 4, )])
这些保留属性,但显然如果存在冲突,这是不可能的。 H
的属性优先。
还有其他选项可以执行symmetric difference, intersection,...
如果您有多个图表要连接在一起,您可以使用compose_all
,它只是在compose
周围包裹了一个for 循环。
【讨论】:
当我们使用nx.draw_networkx(G) nx.draw_networkx(H) nx.draw_networkx(F) plt.show()
绘制所有图时,如何强制所有图共享相同标签的节点的相同位置?我的意思是,节点 1
的坐标对于所有 3 个图形应该是相同的。
@Sigur 绘图命令采用(可选)输入pos
,如nx.draw_networkx(G, pos=pos)
。 pos
是一个字典,其键是节点,值是它们的 (x,y) 坐标。你可以自己定义它,或者通过一些layout
命令。例如,pos = nx.spring_layout(F)
.
我想先使用布局以获得良好的显示效果,然后在添加新边并在其他窗口中再次绘图时使用相同的坐标。或多或少我想生成一系列数字来显示一种图表的时间线。
@Joel - 很棒的答案!谢谢。你知道这是否可以用图表来实现?在我的例子中,一些节点实际上是图对象,而这些图包含其他节点(可能更多图)。 compose 函数最终将所有内容组合在一起。我想这归结为哈希值或类似的东西。只是想知道你以前是否尝试过这个?【参考方案3】:
做到了。
U=nx.Graph()
U.add_edges_from(G.edges()+H.edges())
U.add_nodes_from(G.nodes()+H.nodes()) #deals with isolated nodes
或者,保留边缘属性:
U.add_edges_from(G.edges(data=True)+H.edges(data=True))
并且,还要保留节点属性:
U.add_nodes_from(G.nodes(data=True)+H.nodes(data=True))
【讨论】:
在 NetworkX 2.2 G.edges() 必须在添加之前转换为列表。特别是在需要 MultiGraph 时。以上是关于组合(加入)networkx Graphs的主要内容,如果未能解决你的问题,请参考以下文章