Python Networkx:提取包含给定节点的连接组件(有向图)

Python Networkx:提取包含给定节点的连接组件(有向图),python,networkx,Python,Networkx,我试图从一个大图中提取包含特定节点的所有连接节点的子图 Networkx库中是否有解决方案 [编辑] 我的图是有向图 [编辑] 简单地说: 我希望图形中包含我的特定节点N_I的部分,以及使用任何传入或传出边直接或间接连接(通过其他节点)的所有节点。 例如: 我期望的结果是: >>> g2 = getSubGraph(g, 'B') >>> g2.nodes() ['A', 'B', 'C'] >>> g2.edges() [('A', 'B'

我试图从一个大图中提取包含特定节点的所有连接节点的子图

Networkx库中是否有解决方案

[编辑]
我的图是有向图

[编辑]
简单地说:
我希望图形中包含我的特定节点N_I的部分,以及使用任何传入或传出边直接或间接连接(通过其他节点)的所有节点。
例如:

我期望的结果是:

>>> g2 = getSubGraph(g, 'B')
>>> g2.nodes()
['A', 'B', 'C']
>>> g2.edges()
[('A', 'B'), ('B', 'C')]

使用本页末尾的示例

只需确保引用列表中的最后一个元素,而不是第一个元素

>>> G=nx.path_graph(4)
>>> G.add_edge(5,6)
>>> H=nx.connected_component_subgraphs(G)[-1]

只需在子图中循环,直到目标节点包含在子图中

对于有向图,我假设子图是这样一个图:每个节点都可以从其他节点访问。这是一个子图,其
networkx
函数为

(MWE)最小工作示例:

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()

对于有向子图(有向图)示例,将相应的行更改为:

G = nx.erdos_renyi_graph(30,.05, directed=True)
...
for h in nx.strongly_connected_component_subgraphs(G):

请注意,其中一个节点位于连接组件中,但不在强连接组件中

您可以使用shortest_path()查找可以从给定节点访问的所有节点。在您的情况下,您需要首先将图形转换为无向表示,以便遵循输入和输出边

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')]
还是一行

In [10]: s = g.subgraph(nx.shortest_path(g.to_undirected(),'B'))

In [11]: s.edges()
Out[11]: [('A', 'B'), ('B', 'C')]

我找到了三种解决方案来解决你的需求,和我的一样。我的有向图的大小在6000到12000个节点之间,最大子图大小将达到3700个。我使用的三个功能是:

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)
试验结果总结如下:


在我看来,这将提取最大的子图,而不是“包含特定节点”的子图(如OP注释所示)。@Hooked:我被主题误导了
提取最小的连接子图
,在这种情况下,当返回的列表按大小降序排序时,。相反,如果OP想要具有特定节点的子图,您的解决方案是有意义的。当前文档中最相关的页面是(
connected\u component\u subgraphs
本身已消失。)@Albansouper如前所述的
强connected\u component\u subgraphs
可以处理有向图(有向图)。我是图形方面的新手,但在我看来,在有向图中,子图不是强连通的。。。考虑一个有向路径图…@AlbanSoupper当你说“子图”时,不清楚你想要什么。。。如果没有数学定义的链接,你将很难得到帮助。当你第一次问问题时,像有向图或无向图这样的细节也很重要!对不起,我将重新表述我的问题,让我接受你的答案,因为如果我使用的是无向图,这将是一个完美的答案:)谢谢。你的问题不清楚你想要什么子图。如果你想要一个包含节点N_i且没有孤立节点的子图,例如N_i的邻居满足这个条件。如果希望最大的子图包含N_i但没有孤立节点,则从图中删除所有孤立节点将有效(只要N_i不是0度)。那张图不一定是连在一起的。如果你希望所有的节点都可以从NSI中考虑NX.SuxTestIOPATH(G,NSI)……不确定你是否正在检查,但是请检查我的标题的编辑。你所遇到的并不是你最终提出的问题。
create\u subgraph\u shortpath(G,node)
为我找到了有向图的连通部分。然而,我觉得我可能忽略了API中的一个明显的函数,直接为有向图获得这样的结果。对于
图形
而言,相比之下,使用
连接的组件()
非常容易。
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)