networkx:创建一个由边缘引起的子图

时间:2013-04-22 15:12:33

标签: python graph networkx

networkx只有一个功能

  

Graph.subgraph()

创建从节点引发的子图。 但如何从边缘列表构建子图?

谢谢!

5 个答案:

答案 0 :(得分:3)

如果你有一个边缘列表,那么你已经有了子图。只需在列表中调用nx.Graph,并可选择添加原始图中的(未连接)节点。来自docs

Graph.__init__(data=None, **attr)
  

使用边,名称,图形属性初始化图形   用于初始化图形的数据。如果data = None(默认),则创建一个空图。数据可以是边缘列表,也可以是任何NetworkX图形对象。

答案 1 :(得分:2)

如果你想拥有一个具有Graph.subgraph()属性的函数用于从节点创建的子图,但是这个函数适用于边的迭代器,你需要保持对原始图,边和节点的引用能够传播图形,边缘或节点数据属性的变化。特别是来自Graph.subgraph()的文档字符串:

  

图形,边缘或节点属性仅指向原始图形。   因此,对节点或边缘结构的更改不会反映在   原始图表,而属性的更改将。

     

使用自己的边/节点属性副本创建子图   使用:nx.Graph(G.subgraph(nbunch))

     

如果edge属性是容器,则可以使用以下方法获取深层副本:   G.subgraph(nbunch).copy()

目前提出的方法不会在原始图表中反映其属性的变化,因为它们将从头开始创建新图表。

没有内置的功能/方法来实现边缘列表。但是这个函数使用节点.subgraph的基础结构,因此应该适用于Graph和DiGraph。它不适用于MultiGraph和MultiDiGraph。这是因为MultiGraph和MultiDiGraph可能需要您引用边的键,并且当前方法在第二个之后忽略参数,以便对传入的边列表是否具有作为字典附加的属性不敏感。此外,即使创建时没有引用(通过传递ref_back=False),它也不会使用nx.Graphnx.DiGraph类初始化程序创建新图形,而是使用原始图形的深层复制。有可能扩展它以涵盖其他情况......但我现在不需要它,直到有人明确要求它我会假设没有其他人这样做(见github如果你想看到我在实践中使用的版本)。

def subgraph_from_edges(G,edge_list,ref_back=True):
    """
    Creates a networkx graph that is a subgraph of G
    defined by the list of edges in edge_list.        

    Requires G to be a networkx Graph or DiGraph
    edge_list is a list of edges in either (u,v) or (u,v,d) form
    where u and v are nodes comprising an edge, 
    and d would be a dictionary of edge attributes

    ref_back determines whether the created subgraph refers to back
    to the original graph and therefore changes to the subgraph's 
    attributes also affect the original graph, or if it is to create a
    new copy of the original graph. 
    """

    sub_nodes = list({y for x in edge_list for y in x[0:2]})
    edge_list_no_data = [edge[0:2] for edge in edge_list]
    assert all([e in G.edges() for e in edge_list_no_data])

    if ref_back:
        G_sub = G.subgraph(sub_nodes)
        for edge in G_sub.edges():
            if edge not in edge_list_no_data:
                G_sub.remove_edge(*edge)
    else:
        G_sub = G.subgraph(sub_nodes).copy()
        for edge in G_sub.edges():
            if edge not in edge_list_no_data:
                G_sub.remove_edge(*edge)

    return G_sub

诀窍是可以从图中安全地删除边缘中不存在的任何节点(给我们节点子集),然后您可以删除边缘列表中剩余但不存在的任何边。 / p>

注意:我意识到这现在是一个相当古老的问题,但如果解释为提问者想要一个直接引用原始图形,边缘和节点的图形的情况,所提供的答案实际上并未回答问题(特别是包括他们的数据属性)。我需要这个解决方案,所以我想我会发布它。

答案 2 :(得分:1)

@larsmans的回答是正确的。这是一个简单的例子:

In [1]: import networkx as nx

In [2]: G = nx.path_graph(6)

In [3]: G.edges()
Out[3]: [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)]

In [4]: subgraph_edges = [(1,2), (3,4)]

In [5]: S = nx.Graph(subgraph_edges)

In [6]: S.edges()
Out[6]: [(1, 2), (3, 4)]

答案 3 :(得分:0)

在前面的答案的基础上,保留原始图表及其所有属性的一个非常简单的解决方法可能是:

FG = nx.Graph(fedges)
G = G.subgraph(FG.nodes())

此处, fedges 是用于构建子图的过滤边的列表。首先,使用过滤的边创建一个新的临时图( FG )。然后使用节点列表( FG.nodes())从原始图中获取子图。因为,您实际上是在原始图形对象上使用子图函数,所以您不会从中删除任何属性。

答案 4 :(得分:0)

根据dbn的评论,networkx现在包括一个函数nx.edge_subgraph。它保留了原始图中的属性,但是对这些属性的更改将反映在原始图中。

(awesome=questions)