简体   繁体   中英

NetworkX DiGraph() to Graph() with edge weights not summed, how to sum weights?

I have some relational data that I want to load into NetworkX, and ultimately convert it to a weighted Graph.

By nature, the relational edges are directed and weighted, and I want to retain the weight attribute during when I transform the graph. Using the following code, I've been able to load the relational edges from a dictionary to a MultiDiGraph() :

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

Then, I convert the MultiDiGraph() to a DiGraph() , and condense duplicate edges into one and update the edge weight for each edge:

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

From here, I want to convert the DiGraph() to a Graph() , and again retain and condense the edge weight:

g = G.to_undirected()

But the problem that I have is that it just seems to retain the first edge weight found for 'a' -> 'b' or 'b' -> 'a' .

What I want is the sum of these edges to be maintained as a weight when going to an undirected edge.

Below is a sample show what I'm working with:

# 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})]

Ultimately, I want the edge weight in the undirected graph to be as follows, but I can't figure out if this is an option with G.to_undirected or how to do this:

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

G.to_undirected() can not be used to control what data the undirected edges get, see networkx docs

You may instead do the following:

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)

Basically, you create a new undirected Graph g and populate it with all edges in the directed Graph G. At this point you also initialize the edges' weights to 0. Lastly, you just add the weights to each edge in the undirected graph. Note that in the undirected graph edge (u, v) is the same as (v, u).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM