簡體   English   中英

networkx:創建從邊誘導的子圖

[英]networkx:creating a subgraph induced from edges

networkx 只有一個功能

Graph.subgraph()

創建從節點導出的子圖。 但是如何從邊列表構造子圖?

謝謝 !

如果你有一個邊列表,那么你已經有了子圖。 只需在列表上調用nx.Graph ,並可選擇從原始圖中添加(未連接的)節點。 文檔

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

使用邊、名稱、圖屬性初始化圖。
用於初始化圖形的數據。 如果 data=None(默認),則創建一個空圖。 數據可以是邊列表或任何 NetworkX 圖對象。

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

如果您想要一個函數具有Graph.subgraph()為從節點創建的子圖所具有的屬性,但該函數適用於邊的迭代器,則需要保留對原始圖形、邊和節點的引用,以便能夠傳播圖形、邊或節點數據屬性的變化。 值得注意的是來自Graph.subgraph()的文檔字符串:

圖、邊或節點屬性僅指向原始圖。 因此,對節點或邊結構的更改不會反映在原始圖中,而對屬性的更改會。

要使用自己的邊/節點屬性副本創建子圖,請使用:nx.Graph(G.subgraph(nbunch))

如果邊緣屬性是容器,則可以使用以下方法獲取深層副本: G.subgraph(nbunch).copy()

當前提出的方法不會將其屬性的變化反映回原始圖中,因為它們將從頭開始創建一個新圖。

沒有內置的函數/方法可以使用邊列表來完成此操作。 但是這個函數使用節點.subgraph的基礎.subgraph ,因此應該適用於 Graph 和 DiGraph。 它不適用於不是 MultiGraph 和 MultiDiGraph。 這是因為 MultiGraph 和 MultiDiGraph 可能需要您引用邊的鍵,而當前方法會忽略第二個之后的參數,以便對傳入的邊列表是否具有附加為字典的屬性不敏感。 此外,即使它是在沒有引用的情況下創建的(通過傳遞ref_back=False ),它也不會使用nx.Graphnx.DiGraph類初始值nx.DiGraph項創建新圖,而是原始圖的nx.Graph nx.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

訣竅是可以從圖中安全地切除任何不存在於邊中的節點(給我們我們的節點子集),然后您可以刪除任何保留但不在邊列表中的邊。

注意:我意識到這現在是一個相當古老的問題,但是如果將其解釋為提問者想要一個直接引用原始圖、邊和節點(特別是包括它們的數據)的圖的情況,所提供的答案實際上並沒有回答這個問題屬性)。 我需要那個解決方案,所以我想無論如何我都會發布它。

基於之前的答案,保留原始圖形及其所有屬性的一個非常簡單的解決方法可能是:

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

在這里, fedges是用於構建子圖的過濾邊列表。 首先,使用過濾的邊創建一個新的臨時圖 ( FG )。 然后使用節點列表( FG.nodes() )從原始圖中獲取子圖。 因為,您實際上是在原始圖形對象上使用subgraph函數,所以您不會從中丟失任何屬性。

根據dbn的評論, networkx 現在包含一個函數nx.edge_subgraph來執行此操作。 它保留了原始圖中的屬性,但是對這些屬性的更改將反映在原始圖中。

G = nx.path_graph(5)
S = G.edge_subgraph([(0, 1), (3, 4)])
list(S.nodes) # [0, 1, 3, 4]
list(H.edges) # [(0, 1), (3, 4)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM