将带边属性的有向图转为无向图时,如何保留所有边及属性?
有向多重图转无向图时保留所有边属性的问题
我尝试将带边属性的有向网络图转换为无向图并保留所有边属性,但转换后丢失了weight为3的边。以下是复现代码:
import networkx as nx g = nx.MultiDiGraph() g.add_edge(1, 2, weight= 3) g.add_edge(1, 2, weight= 4) g.add_edge(2, 1, weight= 5) g.add_edge(1, 3, weight= 2) g.add_edge(2, 3, weight= 1) # 添加节点属性 g.nodes[1]["property"] = "A" g.nodes[2]["property"] = "B" g.nodes[3]["property"] = "C" print(g.edges(data=True)) print(g.nodes(data=True)) print("_____________________________________________"*2) h = g.copy().to_undirected(reciprocal=False) print(h.edges(data=True)) print(h.nodes(data=True))
输出结果显示weight为3的边丢失,且部分边的weight被合并:
[(1, 2, {'weight': 3}), (1, 2, {'weight': 4}), (1, 3, {'weight': 2}), (2, 1, {'weight': 5}), (2, 3, {'weight': 1})] [(1, {'property': 'A'}), (2, {'property': 'B'}), (3, {'property': 'C'})] __________________________________________________________________________________________ [(1, 2, {'weight': 9}), (1, 3, {'weight': 2}), (2, 3, {'weight': 1})] [(1, {'property': 'A'}), (2, {'property': 'B'}), (3, {'property': 'C'})]
我需要保留所有三条边,得到如下结果:
[(1, 2, {'weight': 3}), (1, 2, {'weight': 4}), (1, 2, {'weight': 5}), (1, 3, {'weight': 2}), (2, 3, {'weight': 1})]
这不是NetworkX的bug,是默认行为导致的
to_undirected()方法默认会合并同对节点间的边,对于数值型属性(比如weight),默认的聚合逻辑是求和。当设置reciprocal=False时,它会把所有方向的边转为无向边,但合并逻辑会将(1,2)、(2,1)的边合并,导致属性被聚合,部分边的原始属性丢失。
解决方案:手动遍历添加所有边
要保留所有边及其原始属性,需要创建一个无向多重图(MultiGraph),然后手动遍历原有的有向图的所有边,逐个添加到新图中。这样可以避免默认的合并逻辑,完整保留每条边的属性。
修改后的代码如下:
import networkx as nx g = nx.MultiDiGraph() g.add_edge(1, 2, weight=3) g.add_edge(1, 2, weight=4) g.add_edge(2, 1, weight=5) g.add_edge(1, 3, weight=2) g.add_edge(2, 3, weight=1) # 添加节点属性 g.nodes[1]["property"] = "A" g.nodes[2]["property"] = "B" g.nodes[3]["property"] = "C" # 创建空的无向多重图 h = nx.MultiGraph() # 复制所有节点及其属性 h.add_nodes_from(g.nodes(data=True)) # 遍历原有的每条边,添加到无向图中 for u, v, attrs in g.edges(data=True): h.add_edge(u, v, **attrs) # 输出结果 print(h.edges(data=True)) print(h.nodes(data=True))
运行后会得到预期的输出:
[(1, 2, {'weight': 3}), (1, 2, {'weight': 4}), (1, 2, {'weight': 5}), (1, 3, {'weight': 2}), (2, 3, {'weight': 1})] [(1, {'property': 'A'}), (2, {'property': 'B'}), (3, {'property': 'C'})]
内容的提问来源于stack exchange,提问作者Rishan
相关产品推荐
相关产品推荐

