如何在Networkx中将具有共同起始节点的两个边和节点合并为一个?

3

我对networkx不太熟悉,现在向Stackeroverflow社区求助。

我正在尝试将具有共同起始节点的节点和边组合在一起,如下图所示。箭头显示了预期结果。

Italian Trulli

nodes_to_combine = [n for n in graph.nodes if len(list(graph.neighbors(n))) == 2]
for node in nodes_to_combine:
    graph.add_edge(*graph.neighbors(node))
nx.draw(graph, with_labels=True)

有人能帮我弄清楚这个问题吗?


请打印“edgelist”,以便可以复制。 - yatu
@yatu,感谢您的回复。您能给我一些关于如何使用边列表(edgelist)的提示吗? - user6053895
我的意思是,如果你能分享一份边列表的样本,以便让这个过程可以复现。 - yatu
你需要更改节点名称吗?或者如果你的新节点被命名为“20”,这样可以吗?如果可以,看一下“contracted_nodes”。 - Joel
1个回答

2

NetworkX没有合并图中节点的功能,因此需要手动实现。以下是一个没有属性合并的示例(它可以有自己的逻辑):

def merge(G, n1, n2):
    # Get all predecessors and successors of two nodes
    pre = set(G.predecessors(n1)) | set(G.predecessors(n2))
    suc = set(G.successors(n1)) | set(G.successors(n2))
    # Create the new node with combined name
    name = str(n1) + '/' + str(n2)
    # Add predecessors and successors edges
    # We have DiGraph so there should be one edge per nodes pair
    G.add_edges_from([(p, name) for p in pre])
    G.add_edges_from([(name, s) for s in suc])
    # Remove old nodes
    G.remove_nodes_from([n1, n2])

以下是它的工作原理:
import networkx as nx

G = nx.DiGraph()
G.add_edges_from([
    ('0','20'),
    ('10','20'),
    ('10','30'),
    ('20','40'),
    ('30','50'),
])
nx.draw(
    G,
    pos=nx.nx_agraph.graphviz_layout(G, prog='dot'),
    node_color='#FF0000',
    with_labels=True
)

enter image description here

merge(G, '20', '30')
nx.draw(
    G,
    pos=nx.nx_agraph.graphviz_layout(G, prog='dot'),
    node_color='#FF0000',
    with_labels=True
)

enter image description here


非常感谢您的解释和示例。还有一个问题,如果该函数能够自行检测共享公共节点的边缘而不是提供节点会怎样呢?从您的示例中可以看出,20和30共享一个公共节点,即10。因此,该函数应找到共同的节点(10)并将节点(即20和30)组合在一起。这也可能实现吗?感谢您的时间。 - user6053895
1
这个函数只是合并给定属性中的两个节点。您可以尝试使用一些循环来查找图形节点中的公共节点,然后为所需的节点调用此“merge”函数。如果您需要一些特定的节点三元组,则应使用特定的循环(例如像nx.chain_decomposition这样的循环)。 - vurmux
networkx确实有一个合并节点的算法:contracted_nodes。不确定它是否能够完成此处所需的所有操作。 - Joel
@vurmux 我试图使用for循环迭代,并在循环内调用您的函数。如果您有时间,能帮我吗?for n1, n2, attr in list(G.edges(data ='True')):predecessors1 = [pred for pred in G.predecessors(n1)] predecessors2 = [pred for pred in G.predecessors(n2)]#检查它们是否具有相似的前任 if (predecessors1 == predecessors1): merge(G, n1, n2):nx.draw(G, pos=nx.shell_layout(g1), node_color='#FF0000', with_labels=True)如果您有时间,能帮我吗?我已经尝试了过去24小时,感到非常疲惫。谢谢。 - user6053895
1
@Joel 哇,我不知道有这个函数!谢谢你!但是它的工作方式有点不同——它会创建一个新图形并将一个节点合并到另一个节点中(而不是将它们组合在一起)。但无论如何,在边缘合并自动化方面,它都很好用。 - vurmux
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接