Networkx: extract the connected component containing a given node (directed graph)
我试图从一个大图中提取包含特定节点的所有连接节点的子图。
Networkx库中是否有解决方案?
[编辑]
我的图是DiGraph
[编辑]
措辞简单:
我希望图形中包含特定节点N_i以及使用任何传入或传出边直接或间接(通过其他节点)连接的所有节点的图部分。
例:
1 2 3 4 5 | >>> g = nx.DiGraph() >>> g.add_path(['A','B','C',]) >>> g.add_path(['X','Y','Z',]) >>> g.edges() [('A', 'B'), ('B', 'C'), ('Y', 'Z'), ('X', 'Y')] |
我想要的结果是:
1 2 3 4 5 | >>> g2 = getSubGraph(g, 'B') >>> g2.nodes() ['A', 'B', 'C'] >>> g2.edges() [('A', 'B'), ('B', 'C')] |
您可以使用shortest_path()查找给定节点可到达的所有节点。在您的情况下,您需要首先将图形转换为无向表示,以便同时跟踪内部和外部。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | In [1]: import networkx as nx In [2]: >>> g = nx.DiGraph() In [3]: >>> g.add_path(['A','B','C',]) In [4]: >>> g.add_path(['X','Y','Z',]) In [5]: u = g.to_undirected() In [6]: nodes = nx.shortest_path(u,'B').keys() In [7]: nodes Out[7]: ['A', 'C', 'B'] In [8]: s = g.subgraph(nodes) In [9]: s.edges() Out[9]: [('A', 'B'), ('B', 'C')] |
或一行
1 2 3 4 | In [10]: s = g.subgraph(nx.shortest_path(g.to_undirected(),'B')) In [11]: s.edges() Out[11]: [('A', 'B'), ('B', 'C')] |
只需循环遍历子图,直到目标节点包含在子图中。
对于有向图,我假设子图是一个图,这样每个其他节点都可以访问每个节点。这是一个紧密连接的子图,其
(MWE)最小的工作示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import networkx as nx import pylab as plt G = nx.erdos_renyi_graph(30,.05) target_node = 13 pos=nx.graphviz_layout(G,prog="neato") for h in nx.connected_component_subgraphs(G): if target_node in h: nx.draw(h,pos,node_color='red') else: nx.draw(h,pos,node_color='white') plt.show() |
对于有向子图(图)示例,将相应的行更改为:
1 2 3 | G = nx.erdos_renyi_graph(30,.05, directed=True) ... for h in nx.strongly_connected_component_subgraphs(G): |
请注意,节点之一在连接的组件中,但不在强连接的组件中!
我发现了三种解决您的要求的解决方案,与我的一样。我的Digraph的大小在6000到12000个节点之间,最大子图大小将达到3700。我使用的三个函数是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def create_subgraph_dfs(G, node): """ bidirection, O(1)""" edges = nx.dfs_successors(G, node) nodes = [] for k,v in edges.items(): nodes.extend([k]) nodes.extend(v) return G.subgraph(nodes) def create_subgraph_shortpath(G, node): """ unidirection, O(1)""" nodes = nx.single_source_shortest_path(G,node).keys() return G.subgraph(nodes) def create_subgraph_recursive(G, sub_G, start_node): """ bidirection, O(nlogn)""" for n in G.successors_iter(start_node): sub_G.add_path([start_node, n]) create_subgraph_recursive(G, sub_G, n) |
测试结果总结如下:
在connected_component_subgraphs页面的末尾使用示例。
只要确保引用列表中的最后一个元素,而不是第一个
1 2 3 | >>> G=nx.path_graph(4) >>> G.add_edge(5,6) >>> H=nx.connected_component_subgraphs(G)[-1] |