从 networkx 中的有向图中删除节点,同时保留子节点并重新映射它们的边

Nap*_*rty 4 python graph-theory networkx

我想以这样的方式从DiGraphinnetworkx中删除节点,即保留所有子节点并将它们的边重新映射(或删除旧边+创建新边)到其父节点的父节点。节点将根据节点属性(例如属于哪个组)被删除。

删除节点组 B

例如,我希望以编程方式删除具有属性的节点Group B,并将所有直接子节点重新映射到原始父节点(在多个祖父母的情况下,我想映射到所有祖父母)。

我可以想到一种粗略的方法,通过迭代DiGraph,查看其直接后继者和前任者,在它们之间创建关系,然后删除节点,但也许还有更优雅的方法吗?

for node in DiG.nodes(data=True):
  if node[1].get('node_group') == "Group B":
    pre = DiG.predecessors(node[0])
    suc = DiG.successors(node[0])
    for p in pre:
      for s in suc:
        DiG.add_edge(s, p) 
    DiG.remove_node(node[0])
Run Code Online (Sandbox Code Playgroud)

yat*_*atu 5

实现此目的的一种方法是识别要“删除”的节点,并将它们与其前任节点或“父”节点签订合同。边收缩会从图中删除一条边并合并先前连接的两个节点。

因此,检查您提出的小示例:

from networkx.drawing.nx_agraph import graphviz_layout

edgelist = [('Group A', 'Group B'), ('Group B', 'Group C'), 
            ('Group B', 'Group D'), ('Group B', 'Group E')]
G = nx.from_edgelist(edgelist, create_using=nx.DiGraph)

plt.figure(figsize=(6,6))
pos=graphviz_layout(G, prog='dot')
nx.draw(G, pos=pos,
        node_color='lightgreen', 
        node_size=1500,
        with_labels=True, 
        arrows=True)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

现在我们可以找到有问题的节点,并用以下方法收缩将它们链接到其前身之一的边nx.contracted_nodes:

parent = next(G.predecessors('Group B'))
G = nx.contracted_edge(parent, 'Group B')

plt.figure(figsize=(6,6))
nx.draw(G, pos=pos,
        node_color='lightgreen', 
        node_size=1500,
        with_labels=True, 
        arrows=True)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述