8

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.

4 Answers 4

6

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) 
Sign up to request clarification or add additional context in comments.

Comments

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:
Unweighted

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 

Weighted

You can see node (14, 13) has the heaviest line and the largest value from the DataFrame df (besides the (13,13)).

2 Comments

at nx.Multigraph() i am getting this error: TypeError: unhashable type: 'dict'
It should work if you make the change noted in the paragraph right before that code block. Another link to the SO question & the GH Issue. Also, it will work if you remove the create_using argument altogether, only if you know that your graph is a Graph and not a MultiGraph.
4
+50

If you are in Linux, and assuming your csv file looks like this (for example):

23;89;3.49 23;14;1.29 75;14;2.85 14;75;2.9 75;23;0.9 23;27;4.9 

You may use this program:

import os def build_G(csv_file): #init graph dict g={} #here we open csv file with open(csv_file,'r') as f: cont=f.read() #here we get field content for line in cont.split('\n'): if line != '': fields=line.split(';') #build origin node if g.has_key(fields[0])==False: g[fields[0]]={} #build destination node if g.has_key(fields[1])==False: g[fields[1]]={} #build edge origin>destination if g[fields[0]].has_key(fields[1])==False: g[fields[0]][fields[1]]=float(fields[2]) return g def main(): #filename csv_file="mynode.csv" #build graph G=build_G(csv_file) #G is now a python dict #G={'27': {}, '75': {'14': 2.85, '23': 0.9}, '89': {}, '14': {'75': 2.9}, '23': {'27': 4.9, '89': 3.49, '14': 1.29}} #write to file f = open('dotgraph.txt','w') f.writelines('digraph G {\nnode [width=.3,height=.3,shape=octagon,style=filled,color=skyblue];\noverlap="false";\nrankdir="LR";\n') f.writelines for i in G: for j in G[i]: #get weight weight = G[i][j] s= ' '+ i s += ' -> ' + j + ' [dir=none,label="' + str(G[i][j]) + '",penwidth='+str(weight)+',color=black]' if s!=' '+ i: s+=';\n' f.writelines(s) f.writelines('}') f.close() #generate graph image from graph text file os.system("dot -Tjpg -omyImage.jpg dotgraph.txt") main() 

I was previously looking for an effective solution to built complex graph and this is the most simple (without any python module dependency) method I found.

Here is the image result for an undirected graph (using dir=none):

enter image description here

6 Comments

You may use sudo apt-get install graphviz from your terminal if dot binary is not existing on your system
@ Stefani Thanks..!! My graph is undirected, How can I remove the directions.
@user1659936 You are welcome, you need to add dir=none during construction, so please replace the line : s += ' -> ' + j + ' [label="' + str(G[i][j]) + '",penwidth='+str(weight)+',color=black]' by s += ' -> ' + j + ' [dir=none,label="' + str(G[i][j]) + '",penwidth='+str(weight)+',color=black]' to remove direction
@user1659936: I change the code according to your need. Regards
Using the code above, my dotgraph.txt file was generated (seemingly) correctly on Windows, but I can't find the .png output. How can I get this to work on Windows and not just Linux?
|
0

You should edit the line at the beginning of the csv file as follows:

source target type weight 23 89 undirected 34.9 (i.e. there is an edge between node 23 and 89 with weight 34.9) 75 14 undirected 28.5 so on....

After that you can import the csv file into Gephi to represent the graph which the thickness of the edges stands for the weight, for example: enter image description here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.