【问题标题】:Combine (join) networkx Graphs组合(加入)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))

标签: python graph-theory networkx


【解决方案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 时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    相关资源
    最近更新 更多