2013-04-22 92 views
3

networkx具有如下功能:networkx:創建從邊緣引起的子圖僅

Graph.subgraph()

創建從節點引起的子圖。 但如何從邊緣列表構造一個子圖?

謝謝!

+0

您是否在意圖表是否實際指向原始對象(以便邊緣會引用原始圖形的邊緣)?它們在下面描述的方式實際上是等效的(對於'nx.Graph''G'類型的原始圖形)'G.subgraph(nbunch).copy()'(參見https://networkx.readthedocs.org/en /latest/reference/generated/networkx.Graph.subgraph.html#networkx.Graph.subgraph)。如果你想以某種方式做到這一點,我認爲你需要一種不同的方法。我可能需要這樣做,如果我解決了問題,我會發佈一個答案。 – mpacer 2015-11-24 21:19:50

+0

我看到一個[Graph.edge_subgraph](https://networkx.readthedocs.org/en/latest/reference/generated/networkx.Graph.edge_subgraph.html#networkx.Graph.edge_subgraph)方法,但它沒有出現在我有(1.10)的networkx版本中可用。 – dbn 2016-03-28 20:08:15

+0

@dbw它最近一定是被實現的,我很喜歡它的實現。不確定我喜歡你是否已經單獨聲明瞭一個副本而不是傳遞參數,但是API的一致性可能是有意義的。 – mpacer 2016-03-31 22:31:00

回答

3

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

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

初始化與邊緣,名稱,圖形的屬性的圖表。
要初始化圖形的數據。如果數據=無(默認),則會創建一個空圖。數據可以是邊緣列表或任何NetworkX圖形對象。

+0

希望您不介意,我通過添加指向文檔的鏈接以及頁面上的一些更有用的信息來改進您的答案。 – Hooked 2013-04-22 16:01:39

+0

我已經有了一個圖g,我想創建一個基於子圖的子圖邊。 igraph包有相關的功能,但似乎networkx只能建立從節點誘發的子圖 – user2281114 2013-04-22 16:56:06

+0

@Hooked:謝謝! – 2013-04-23 12:09:04

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)] 
+0

這對networkx運行良好,謝謝! igraph必須收到連續號碼,所以我混淆了兩個問題。 – user2281114 2013-04-23 01:29:28

1

如果你想有一個有Graph.subgraph()具有從節點創建子圖,而是該功能適用​​於邊緣的迭代器屬性的功能,你需要保持引用到原圖,邊和節點能夠傳播圖中的變化,邊或節點數據屬性。值得注意的是來自Graph.subgraph()的文檔字符串:

圖形,邊或節點屬性只是指向原始圖。 因此,對屬性所做的更改將不會反映在 原始圖中,對節點或邊緣結構的更改將不會反映出來。

要創建具有其自己的邊緣/節點的拷貝的子圖屬性 使用:nx.Graph(G.subgraph(nbunch))

如果邊緣屬性是容器,可以使用獲得的深層副本: 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 

訣竅是,在邊緣不存在任何節點可以從圖中可以安全地切除(給我們我們的節點子集),然後你可以刪除,但仍然不是你的優勢列表中的任何邊緣。

注:我意識到這是一個相當古老的問題,但提供的答案實際上並不回答這個問題,如果解釋爲提問者想要一個直接引用原始圖,邊和節點的圖特別包括他們的數據屬性)。我需要這個解決方案,所以我想我會發布它。

+0

認識到這是一箇舊帖子,但我正在尋找與MultiDiGraph – Erotemic 2016-03-02 01:57:58

+1

這個功能相比,一些我試圖復興不太舊:)。我現在不能爲MultiDiGraph寫一些東西,但是訣竅就是存儲你想要保留的每個邊的關鍵字。可能需要刪除的行是'edge_list_no_data = [edge_list中的邊緣[0:2]邊緣]'和'G_sub.edges()中的邊緣':'將需要更改爲類似'for edge in G_sub.edges(keys = True):'但是你需要確保'edge_list_no_data'確實有其他行可以工作的鍵。 – mpacer 2016-03-31 22:19:45

+0

雖然很老,但我在這裏貼一些建議,以防有人需要。對於非雙向圖,由於可能的問題,「edge_list_no_data」最好改變爲「edge_list_no_data中的(u,v)或edge_list_no_data中的(v,u)」或「G.has_edge(u,v)」由邊緣節點的順序引起。如果我們只需要來自邊緣的屬性,那麼函數可以很容易地寫成「G_sub = networkx」。如果((u,v)在edge_list中)或(edge_list中的(v,u)),圖形([(u,v,d)對於G.edges(data = True)中的u,v,d)])「 – Young 2017-04-18 15:48:11

0

在以前的答案構建,一個非常簡單的解決方法,保留了原有的曲線與所有的屬性可能是這樣的:

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

這裏,fedges是過濾邊建子圖的列表。首先,創建一個帶有濾波邊緣的新臨時圖(FG)。然後使用節點列表(FG.nodes())從原始圖形中獲取子圖。因爲您實際上使用原始圖形對象上的子圖函數,所以不會從中釋放任何屬性。