My sample data set in CSV format looks as follows.
The undirected graph has 90 nodes represented with numbers {10,11,12....99} whose edges with weights are defined as follows.
[sample data]
node1 node2 weight
23 89 34.9 (i.e. there is an edge between node 23 and 89 with weight 34.9)
75 14 28.5
so on....
I would like to represent this in network form. What is the effective way to represent it (for example Gephi, networkx, etc). Thickness of the edge should represent edge weight.
Network graph is simply called as graph. It consists of a set of nodes connected by branches. In graphs, a node is a common point of two or more branches. Sometimes, only a single branch may connect to the node. A branch is a line segment that connects two nodes.
Using networkx, you can add edges with attributes
import networkx as nx
G = nx.Graph()
G.add_edge(23, 89, weight=34.9)
G.add_edge(75, 14, weight=28.5)
If you have a large csv I'd recommend using pandas
for the I/O portion of your task. networkx
has a useful method to interface with pandas
called from_pandas_dataframe
. Assuming your data is in a csv in the format you stated above, this command should work for you:
df = pd.read_csv('path/to/file.csv', columns=['node1', 'node2', 'weight'])
But for demonstration I'll use 10 random edges within your requirements (you won't need to import numpy
, I'm just using it for random number generation):
import matplotlib as plt
import networkx as nx
import pandas as pd
#Generate Random edges and weights
import numpy as np
np.random.seed(0) # for reproducibility
w = np.random.rand(10) # weights 0-1
node1 = np.random.randint(10,19, (10)) # I used 10-19 for demo
node2 = np.random.randint(10,19, (10))
df = pd.DataFrame({'node1': node1, 'node2': node2, 'weight': w}, index=range(10))
Everything in the previous block should generate the same as your pd.read_csv
command. Resulting in this DataFrame, df
:
node1 node2 weight
0 16 13 0.548814
1 17 15 0.715189
2 17 10 0.602763
3 18 12 0.544883
4 11 13 0.423655
5 15 18 0.645894
6 18 11 0.437587
7 14 13 0.891773
8 13 13 0.963663
9 10 13 0.383442
Use from_pandas_dataframe
to initialize MultiGraph
. This assumes you will have multiple edges connecting to one node (not specified in OP). To use this method, you will have to make an easy change in networkx
source code in the convert_matrix.py
file, implemented here (it was a simple bug).
MG = nx.from_pandas_dataframe(df,
'node1',
'node2',
edge_attr='weight',
create_using=nx.MultiGraph()
)
This generates your MultiGraph, you can visualize it utilizing draw
:
positions = nx.spring_layout(MG) # saves the positions of the nodes on the visualization
# pass positions and set hold=True
nx.draw(MG, pos=positions, hold=True, with_labels=True, node_size=1000, font_size=16)
In detail:
positions
is a dictionary where each node is a key and the value is a position on the graph. I'll describe why we store positions
below. The generic draw
will draw your MultiGraph instance MG
with the nodes at the specified positions
. However, as you can see the edges are all the same width:
But you have everything you need to add the weights. First get the weights into a list called weights
. Iterating (with list comprehension) through each edge with edges
, we can extract the weights. I chose to multiply by 5
because it looked the cleanest:
weights = [w[2]['weight']*5 for w in MG.edges(data=True)]
Finally we'll use draw_networkx_edges
, which only draws the edges of the graph (no nodes). Since we have the positions
of the nodes, and we set hold=True
, we can draw weighted edges right on top of our previous visualization.
nx.draw_networkx_edges(MG, pos=positions, width=weights) #width can be array of floats
You can see node (14, 13)
has the heaviest line and the largest value from the DataFrame df
(besides the (13,13)
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With