V_sqrt
V_sqrt

Reputation: 567

Colour and weights in a network

I would like to create a graph where nodes have a different weight and colour based on values in columns.

A sample of data is

Node Weight Colour Neighbours
1 23 red [3,5]
3 18 blue [2]
4 50 blue []
5 18 blue [1]
2 36 green [3]

The table above shows the links by nodes:

For building the network I have done as follows

d = dict(df.drop_duplicates(subset=['Node','Colour'])[['Node','Colour']].to_numpy().tolist())

nodes = G.nodes()
plt.figure(figsize=(30,30)) 
pos = nx.draw(G, with_labels=True, 
              nodelist=nodes,
              node_color=[d.get(i,'lightgreen') for i in nodes], 
              node_size=1000) 

Unfortunately the colours are all wrong! Also, I have difficulties to add information on weights. The ties among nodes should have weights assigned to them. I have tried with edge_attr='weight' in nx.draw, where 'weight' = df['Weight']. I hope you can give me some help and let me know what I have done wrong.

Upvotes: 1

Views: 259

Answers (1)

willcrack
willcrack

Reputation: 1852

node_color=[d.get(i,'lightgreen') for i in nodes], 

This method of coloring didn't work because you are assigning colors according to the nodes instead of their colours.

"The ties among nodes should have weights assigned to them. I have tried with edge_attr='weight' in nx.draw, where 'weight' = df['Weight']."*

For the solution I present, only the nodes have weights not the edges. If you pretend to do this, add a column on your data frame, e.g:

Node Weight Colour Neighbours Edge_Weights
1 23 red [3,5] [w1_3,w1_5]
3 18 blue [2] [w3_2]
4 50 blue [] []
5 18 blue [1] [w5_1]
2 36 green [3] [w2_3]

Next, add edge weight using G.add_edge(n1,n2,wight=w), here is some documentation.

Since you have multiple attributes you want to add to your nodes I would recommend iterating through your dataframe using for example df.itertuples().

Here is the full code:

df = pd.DataFrame(  data = {'Node': [1, 3, 4, 5, 2], 
                        'Weight': [23, 18 ,50, 18, 36], 
                        'Colour': ["red", "blue", "blue", "blue", "green"], 
                        'Neighbors': [[3,5], [2], [], [1], [3]]
                        }
              )
   

NROWS = None
def get_graph_from_pandas(df:
    
    G = nx.DiGraph() # assuming the graph is directed since e.g node 1 has 
                     # 3 as neighbour but 3 doesnt have 1 as neighbour
    
    
    for row in df.itertuples(): # row is the row of the dataframe
        n = row.Node   # change to row.(name of column with the node names)
        w = row.Weight # change to row.(name of column with the node weights)
        c = row.Colour # change to row.(name of column with the node colors)
        neighbors = row.Neighbors
        
        G.add_node(n, weight = w, colour = c)
        
        for neigh in neighbors:
            #add edge weights here, attribute of G.add_edge
            G.add_edge(n,neigh)  
            
    return G
        
        
        
G = get_graph_from_pandas(df)

print("Done.")
print("Total number of nodes: ", G.number_of_nodes())
print("Total number of edges: ", G.number_of_edges())

pos = nx.draw(G, with_labels=True, 
              node_color=[node[1]['colour'] for node in G.nodes(data=True)], 
              node_size=200)

Upvotes: 1

Related Questions