Networkx:将节点列表合并为新节点并保留边的实现方法
合并NetworkX中多个节点为单个新节点的简洁方法
NetworkX的nx.contracted_nodes仅支持两两合并节点,但我们可以通过迭代合并或函数式封装的方式,实现传入节点列表批量合并为单个新节点的需求。以下是两种实用方案:
方案一:迭代合并+节点重命名
先将目标节点列表中的节点逐个合并到列表的第一个节点作为临时节点,最后将临时节点重命名为目标新节点。
import networkx as nx def nodes_to_collapse(G, nodes_list, new_node): # 复制原图避免修改原始数据 merged_graph = G.copy() # 选取第一个节点作为临时合并载体 temp_node = nodes_list[0] # 迭代合并剩余节点到临时节点 for node in nodes_list[1:]: merged_graph = nx.contracted_nodes(merged_graph, temp_node, node, self_loops=False) # 将临时节点重命名为目标新节点 merged_graph = nx.relabel_nodes(merged_graph, {temp_node: new_node}) return merged_graph # 构建原始图 G = nx.DiGraph() G.add_edges_from([ ('A','B'), ('B','C'), ('C','D'), ('D','E'), ('F','B'), ('B','G'), ('B','D'), ]) # 合并B、C、D为新节点H result_graph = nodes_to_collapse(G, ['B','C','D'], 'H') # 绘制结果图 nx.draw( result_graph, pos=nx.nx_agraph.graphviz_layout(result_graph, prog='dot'), node_color='#FF0000', with_labels=True )
方案二:用functools.reduce简化代码
借助reduce函数可以把迭代合并的逻辑简化为一行代码,让实现更简洁:
import networkx as nx from functools import reduce def nodes_to_collapse(G, nodes_list, new_node): merged_graph = G.copy() # 批量合并所有节点到列表第一个节点 temp_merged = reduce( lambda g, node: nx.contracted_nodes(g, nodes_list[0], node, self_loops=False), nodes_list[1:], merged_graph ) # 重命名临时节点 return nx.relabel_nodes(temp_merged, {nodes_list[0]: new_node}) # 使用方式与方案一完全一致 result_graph = nodes_to_collapse(G, ['B','C','D'], 'H')
关键参数说明
self_loops=False:合并过程中自动移除产生的自环,如果需要保留自环,可将该参数设为True。- 复制原图:如果不需要保留原始图结构,可以直接对原
G进行操作,省去复制步骤。
内容的提问来源于stack exchange,提问作者Robert Alexander
相关产品推荐
相关产品推荐

