组合(加入)networkx Graphs

Posted

技术标签:

【中文标题】组合(加入)networkx Graphs【英文标题】:Combine (join) networkx Graphs 【发布时间】:2015-12-15 14:39:28 【问题描述】:

假设我有两个 networkx 图,GH

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的主要内容,如果未能解决你的问题,请参考以下文章

Python3画图系列——NetworkX初探

python3 networkx

python+networkx

如何用networkx绘制社区

python-networkx学习

用 GraphScope 像 NetworkX 一样做图分析