如何将NetworkX DiGraph()转换为Graph()且边权重不求和,如何求和?

2 投票
1 回答
3811 浏览
提问于 2025-04-21 00:23

我有一些关系数据,想把它们加载到NetworkX中,最后转换成一个加权图。

这些关系边本身是有方向的,并且带有权重,我希望在转换图的时候保留这个权重属性。使用以下代码,我已经能够从一个字典中加载关系边到一个MultiDiGraph()中:

MG = nx.MultiDiGraph([(i['source'],i['target']) for i in edges ])

接着,我把MultiDiGraph()转换成DiGraph(),并把重复的边合并成一条,同时更新每条边的权重:

G = nx.DiGraph()
for (u,v) in MG.edges():
    G.add_edge(u, v, weight=len(MG[u][v]))

然后,我想把DiGraph()转换成Graph(),同样希望保留并合并边的权重:

g = G.to_undirected()

但我遇到的问题是,它似乎只保留了'a' -> 'b''b' -> 'a'中找到的第一条边的权重。

我想要的是在转换成无向边时,能够保留这些边的权重总和。

下面是一个示例,展示了我正在处理的内容:

# relational directed edge data containing duplicate edges 
edges = [{'source': 'a', 'target': 'b'},
         {'source': 'a', 'target': 'b'},
         {'source': 'a', 'target': 'b'},
         {'source': 'b', 'target': 'a'},
         {'source': 'a', 'target': 'c'},
         {'source': 'c', 'target': 'a'},
         {'source': 'c', 'target': 'd'},
         {'source': 'c', 'target': 'd'},
         {'source': 'd', 'target': 'c'}]

# load edges into a MultiDiGraph to maintain direction and duplicate edges
MG = nx.MultiDiGraph([(i['source'],i['target']) for i in edges ])

MG.edges(data=True) = [('a', 'c', {}),
                       ('a', 'b', {}),
                       ('a', 'b', {}),
                       ('a', 'b', {}),
                       ('c', 'a', {}),
                       ('c', 'd', {}),
                       ('c', 'd', {}),
                       ('b', 'a', {}),
                       ('d', 'c', {})]

# convert MultiDiGraph to a DiGraph and update edge weight
G = nx.DiGraph()
for (u,v) in MG.edges():
    G.add_edge(u, v, weight=len(MG[u][v]))

G.edges(data=True) = [('a', 'c', {'weight': 1}),
                      ('a', 'b', {'weight': 3}),
                      ('c', 'a', {'weight': 1}),
                      ('c', 'd', {'weight': 2}),
                      ('b', 'a', {'weight': 1}),
                      ('d', 'c', {'weight': 1})]

# convert DiGraph to a Graph, but edge weight not updated as sum, but first value
g = G.to_undirected()

g.edges(data=True) = [('a', 'c', {'weight': 1}),
                      ('a', 'b', {'weight': 1}),
                      ('c', 'd', {'weight': 1})]

最终,我希望无向图中的边权重如下,但我不知道这是否是G.to_undirected的一个选项,或者该怎么做:

g.edges(data=True) = [('a', 'c', {'weight': 2}),
                      ('a', 'b', {'weight': 4}),
                      ('c', 'd', {'weight': 3})]

1 个回答

5

G.to_undirected() 这个方法不能用来控制无向边的数据,具体可以查看 networkx 的文档

你可以尝试以下方法:

import networkx as nx

G = nx.DiGraph()
G.add_edges_from([('a', 'c', {'weight': 1}),
                  ('a', 'b', {'weight': 3}),
                  ('c', 'a', {'weight': 1}),
                  ('c', 'd', {'weight': 2}),
                  ('b', 'a', {'weight': 1}),
                  ('d', 'c', {'weight': 1})])

print G.edges(data=True)

g = nx.Graph()
g.add_edges_from(G.edges_iter(), weight=0)

print g.edges(data=True)

for u, v, d in G.edges_iter(data=True):
    g[u][v]['weight'] += d['weight']

print g.edges(data=True)

简单来说,你需要创建一个新的无向图 g,并把所有来自有向图 G 的边都放进去。这个时候,你也要把这些边的权重初始化为 0。最后,你只需要给无向图中的每条边添加权重。要注意的是,在无向图中,边 (u, v) 和 (v, u) 是一样的。

撰写回答