networkx:创建由边缘引发的子图。

时间:2023-02-03 19:08:02

networkx only has a function

networkx只有一个函数

Graph.subgraph()

Graph.subgraph()

to create a subgraph induced from nodes. but how to construct a subgraph from edge list ?

创建由节点诱导的子图。但是如何从边缘列表构造子图呢?

thanks !

谢谢!

4 个解决方案

#1


3  

If you have a list of edges, then you already have the subgraph. Just call nx.Graph on the list, and optionally add the (unconnected) nodes from the original graph. From the docs

如果你有一个边的列表,那么你已经有了子图。就叫nx。在列表上的图,可以随意地从原始图中添加(未连接的)节点。从文档

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

Initialize a graph with edges, name, graph attributes.
Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object.

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

#2


2  

If you want to have a function that has the properties that Graph.subgraph() has for subgraphs created from nodes but instead this function works on iterators of edges, you need to keep references to the original graph, edges and nodes to be able to propagate changes in the graph, edge or node data attributes. Notably from the docstring of Graph.subgraph():

如果你想有一个函数的属性Graph.subgraph()创建的子图的节点,而是这个函数适用于迭代器的边缘,你需要保持原始图的引用,边和节点能够传播的变化图表,边缘或节点数据属性。特别是从图的docstring ():

The graph, edge or node attributes just point to the original graph. So changes to the node or edge structure will not be reflected in the original graph while changes to the attributes will.

图、边或节点属性只是指向原始图。因此,对节点或边缘结构的更改将不会在原始图中反映出来,而对属性的更改将会反映出来。

To create a subgraph with its own copy of the edge/node attributes use: nx.Graph(G.subgraph(nbunch))

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

If edge attributes are containers, a deep copy can be obtained using: G.subgraph(nbunch).copy()

如果边缘属性是容器,可以使用:G.subgraph(nbunch).copy()获取深度副本

The currently proposed methods will not reflect changes in their attributes back in the original graph, as they will create a new graph from scratch.

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

There is no built in function/method for accomplishing this with a list of edges. But this function uses the infrastructure of the node .subgraph and thus should work for Graph and DiGraph. It will not work for not MultiGraph and MultiDiGraph. This is because MultiGraph and MultiDiGraph may need you to refer to the key of the edge and the current approach ignores arguments after the second so as to be insensitive to whether the passed in list of edges has attributes attached as a dictionary or not. Also, even when it is created without reference (by passing ref_back=False), it does not create a new graph using the nx.Graph or nx.DiGraph class initializers, but a deepcopy of the original graph. It would be possible to extend it to cover other cases… but I don't need that for now, and until someone explicitly asks for it I'm going to assume that no one else does (see github if you want to see the version that I've used in practice).

函数/方法中没有内置的边列表来实现这一点。但是这个函数使用节点.subgraph的基础结构,因此应该适用于图和有向图。它对非多图和多有向图无效。这是因为MultiGraph和MultiDiGraph可能需要您引用边缘的键,而当前的方法会忽略后面的参数,从而不关心是否传入的边缘列表中包含了作为字典的属性。而且,即使它是在没有引用的情况下创建的(通过ref_back=False),它也不会使用nx创建一个新的图形。图或nx。有向图类初始化器,但是原始图的深度拷贝。可以将它扩展到其他情况……但我现在不需要它,除非有人明确地提出要求,否则我将假定没有其他人会这么做(如果您希望看到我在实践中使用的版本,请参阅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

The trick is that any nodes not present in the edges can be safely excised from the graph (giving us our node subset), and then you can remove any edges that remain but aren't in your edge list.

诀窍在于,任何不存在于边中的节点都可以安全地从图中删除(给出我们的节点子集),然后您可以删除任何保留但不在边列表中的边。

Note: I realize that this is now a fairly ancient question, but the answers provided don't actually answer the question if interpreted as a case where the asker wanted a graph that directly referenced the original graph, edges and nodes (notably including their data attributes). I needed that solution, so I figured I'd post it regardless.

注意:我意识到这现在是一个相当古老的问题,但是如果将所提供的答案解释为需要一个直接引用原始图、边和节点的图(特别是包含它们的数据属性),那么实际上并不能回答这个问题。我需要那个解决方案,所以我想无论如何我都要把它贴出来。

#3


1  

The answer by @larsmans is correct. Here is a simple example:

@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)]

#4


0  

Building up on the previous answers, a really simple workaround to retain the original graph with all its attributes might be this:

在前面的答案的基础上,一个真正简单的方法来保留具有所有属性的原始图形可能是:

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

Here, fedges is the list of filtered edges to build the subgraph. First, create a new temporary graph (FG) with the filtered edges. Then use the node list (FG.nodes()) to get a subgraph from the original graph. Since, you are actually using the subgraph function on the original graph object, you're not going to loose any attributes from it.

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

#1


3  

If you have a list of edges, then you already have the subgraph. Just call nx.Graph on the list, and optionally add the (unconnected) nodes from the original graph. From the docs

如果你有一个边的列表,那么你已经有了子图。就叫nx。在列表上的图,可以随意地从原始图中添加(未连接的)节点。从文档

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

Initialize a graph with edges, name, graph attributes.
Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object.

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

#2


2  

If you want to have a function that has the properties that Graph.subgraph() has for subgraphs created from nodes but instead this function works on iterators of edges, you need to keep references to the original graph, edges and nodes to be able to propagate changes in the graph, edge or node data attributes. Notably from the docstring of Graph.subgraph():

如果你想有一个函数的属性Graph.subgraph()创建的子图的节点,而是这个函数适用于迭代器的边缘,你需要保持原始图的引用,边和节点能够传播的变化图表,边缘或节点数据属性。特别是从图的docstring ():

The graph, edge or node attributes just point to the original graph. So changes to the node or edge structure will not be reflected in the original graph while changes to the attributes will.

图、边或节点属性只是指向原始图。因此,对节点或边缘结构的更改将不会在原始图中反映出来,而对属性的更改将会反映出来。

To create a subgraph with its own copy of the edge/node attributes use: nx.Graph(G.subgraph(nbunch))

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

If edge attributes are containers, a deep copy can be obtained using: G.subgraph(nbunch).copy()

如果边缘属性是容器,可以使用:G.subgraph(nbunch).copy()获取深度副本

The currently proposed methods will not reflect changes in their attributes back in the original graph, as they will create a new graph from scratch.

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

There is no built in function/method for accomplishing this with a list of edges. But this function uses the infrastructure of the node .subgraph and thus should work for Graph and DiGraph. It will not work for not MultiGraph and MultiDiGraph. This is because MultiGraph and MultiDiGraph may need you to refer to the key of the edge and the current approach ignores arguments after the second so as to be insensitive to whether the passed in list of edges has attributes attached as a dictionary or not. Also, even when it is created without reference (by passing ref_back=False), it does not create a new graph using the nx.Graph or nx.DiGraph class initializers, but a deepcopy of the original graph. It would be possible to extend it to cover other cases… but I don't need that for now, and until someone explicitly asks for it I'm going to assume that no one else does (see github if you want to see the version that I've used in practice).

函数/方法中没有内置的边列表来实现这一点。但是这个函数使用节点.subgraph的基础结构,因此应该适用于图和有向图。它对非多图和多有向图无效。这是因为MultiGraph和MultiDiGraph可能需要您引用边缘的键,而当前的方法会忽略后面的参数,从而不关心是否传入的边缘列表中包含了作为字典的属性。而且,即使它是在没有引用的情况下创建的(通过ref_back=False),它也不会使用nx创建一个新的图形。图或nx。有向图类初始化器,但是原始图的深度拷贝。可以将它扩展到其他情况……但我现在不需要它,除非有人明确地提出要求,否则我将假定没有其他人会这么做(如果您希望看到我在实践中使用的版本,请参阅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

The trick is that any nodes not present in the edges can be safely excised from the graph (giving us our node subset), and then you can remove any edges that remain but aren't in your edge list.

诀窍在于,任何不存在于边中的节点都可以安全地从图中删除(给出我们的节点子集),然后您可以删除任何保留但不在边列表中的边。

Note: I realize that this is now a fairly ancient question, but the answers provided don't actually answer the question if interpreted as a case where the asker wanted a graph that directly referenced the original graph, edges and nodes (notably including their data attributes). I needed that solution, so I figured I'd post it regardless.

注意:我意识到这现在是一个相当古老的问题,但是如果将所提供的答案解释为需要一个直接引用原始图、边和节点的图(特别是包含它们的数据属性),那么实际上并不能回答这个问题。我需要那个解决方案,所以我想无论如何我都要把它贴出来。

#3


1  

The answer by @larsmans is correct. Here is a simple example:

@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)]

#4


0  

Building up on the previous answers, a really simple workaround to retain the original graph with all its attributes might be this:

在前面的答案的基础上,一个真正简单的方法来保留具有所有属性的原始图形可能是:

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

Here, fedges is the list of filtered edges to build the subgraph. First, create a new temporary graph (FG) with the filtered edges. Then use the node list (FG.nodes()) to get a subgraph from the original graph. Since, you are actually using the subgraph function on the original graph object, you're not going to loose any attributes from it.

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