直截了当的问题:我想检索连接到NetworkX图中给定节点的所有节点,以便创建子图。在下面显示的示例中,我只想提取圆圈内的所有节点,给出其中任何一个节点的名称。
我已经尝试了以下递归函数,但是遇到了Python的递归限制,即使此网络中只有91个节点。
无论下面的代码是否有错误,我尝试实现的最佳方式是什么?我将在各种大小的图表上运行此代码,并且不会事先知道最大递归深度。
def fetch_connected_nodes(node, neighbors_list):
for neighbor in assembly.neighbors(node):
print(neighbor)
if len(assembly.neighbors(neighbor)) == 1:
neighbors_list.append(neighbor)
return neighbors_list
else:
neighbors_list.append(neighbor)
fetch_connected_nodes(neighbor, neighbors_list)
neighbors = []
starting_node = 'NODE_1_length_6578_cov_450.665_ID_16281'
connected_nodes = fetch_connected_nodes(starting_node, neighbors)
答案 0 :(得分:8)
假设图形是无向的,则有一个内置的networkx命令:
node_connected_component(G, n)
文档为here。它返回包含G
的{{1}}的连接组件中的所有节点。
这不是递归的,但我认为你实际上并不需要甚至不需要它。
对您的代码的评论:您遇到了一个通常会导致无限递归的错误。如果n
和u
是度数至少为2的邻居,那么它将以v
开头,将u
放入列表中,并在处理v
时放置列表中v
并继续重复。它需要更改为仅处理不在u
中的邻居。检查它是昂贵的,所以改为使用一套。如果起始节点具有1级,那么也存在一个小问题。您对1级的测试不能完成您所追求的目标。如果初始节点的度数为1,但其邻居的度数较高,则无法找到邻居的邻居。
以下是对代码的修改:
neighbors_list
您可以将其称为def fetch_connected_nodes(G, node, seen = None):
if seen == None:
seen = set([node])
for neighbor in G.neighbors(node):
print(neighbor)
if neighbor not in seen:
seen.add(neighbor)
fetch_connected_nodes(G, neighbor, seen)
return seen
。
答案 1 :(得分:4)
您可以直接从给定节点或任何节点开始使用广度优先搜索。
在Networkx中,您可以使用以下函数从起始节点获取树形图:
bfs_tree(G, source, reverse=False)
以下是doc:Network bfs_tree的链接。
答案 2 :(得分:3)
这是一个递归算法,用于将所有节点连接到输入节点。
def create_subgraph(G,sub_G,start_node):
sub_G.add_node(start_node)
for n in G.neighbors_iter(start_node):
if n not in sub_G.neighbors(start_node):
sub_G.add_path([start_node,n])
create_subgraph(G,sub_G,n)
我认为防止无限递归调用的关键是检查原始图中的邻居节点是否尚未连接到正在创建的sub_G中。否则,您将始终在已经有边缘的节点之间来回移动。
我按如下方式测试了它:
G = nx.erdos_renyi_graph(20,0.08)
nx.draw(G,with_labels = True)
plt.show()
sub_G = nx.Graph()
create_subgraph(G,sub_G,17)
nx.draw(sub_G,with_labels = True)
plt.show()