Search code examples
pythonnetworkx

Changing attributes of nodes


I have the following network:

G = nx.Graph()
G.add_node(0, weight=8)
G.add_node(1, weight=5)
G.add_node(2, weight=3)
G.add_node(3, weight=2)
G.add_node(4, weight=1)
G.add_node(5, weight=5)
G.add_node(6, weight=8)

nx.add_path(G, [0,1,2,5])
nx.add_path(G, [2,6,3])
nx.add_path(G, [3,6])


# labels = {n: G.nodes[n]['weight'] for n in G.nodes}
labels = {
    n: str(n) + '\nweight=' + str(G.nodes[n]['weight']) if 'weight' in G.nodes[n] else str(n)
    for n in G.nodes
}
colors = [G.nodes[n]['weight'] for n in G.nodes]
fig = plt.figure(figsize=(10,10))

nx.draw(G, with_labels=True, labels=labels, node_color=colors)

Each node has its own weight. I am trying to update each node's weight based on the weights' average of its neighbors.

enter image description here

After the update,

  • node 0 should have weight 6.5
  • node 1 should gave weight 5.33
  • node 2 should have weight 5.25
  • node 3 should have weight 5 (as it is linked with 6)
  • node 4 should still have weight 1
  • node 5 should have weight 4
  • node 6 should have weight 4.33

I would say that, for updating the values, I should probably get an iterator over neighbors of node x with G.neighbors(x) or just loop through the nodes, but since I need to calculate the average, it is not easy as I would have expected.


Solution

  • I made you a crazy list comprehension (because they are cool):

    newWeights = \
        [
            sum( # summ for averaging
                [G.nodes[neighbor]['weight'] for neighbor in G.neighbors(node)] # weight of every neighbor
                + [G.nodes[i]['weight']] # adds the node itsself to the average
            ) / (len(list(G.neighbors(node)))+1) # average over number of neighbours+1
            if len(list(G.neighbors(node))) > 0 # if there are no neighbours
            else G.nodes[i]['weight'] # weight stays the same if no neighbours
        for i,node in enumerate(G.nodes) # do the above for every node
        ]
    print(newWeights) # [6.5, 5.333333333333333, 5.25, 5.0, 1, 4.0, 4.333333333333333]
    for i, node in enumerate(G.nodes):
        G.nodes[i]['weight'] = newWeights[i] # writes new weights after it calculated them all.
    
    

    But if you hate fun and list comprehensions you can also use this version:

    newWeights = []
    for i,node in enumerate(G.nodes): # calculates average for every node
        summation = G.nodes[i]['weight'] # weight of node itsself
        for neighbor in G.neighbors(node): # adds the weight of every neighbour
            summation += G.nodes[neighbor]['weight']
        average = summation / (len(list(G.neighbors(node)))+1) # division for average 
        newWeights.append(average) 
    
    print(newWeights)
    for i, node in enumerate(G.nodes):
        G.nodes[i]['weight'] = newWeights[i]