I am trying to visualize a connection matrix of an bi-partite set problem. How do i do this in a way that demonstrates best?
I have started with this using a graphics program yed:
The circles describe a certain kind of connection between red and blue and the squares another. Both red and blue squares will have some kind of text on them.
However it would be nicer to generate this grafic with matplotlib, since i would like to generate this on the fly with data attached. How would i proceed to do that? My data looks kinda like this:
Data:
name_blue name_red Connection Type
bluepart1 redpart1 1
bluepart1 redpart2 1
bluepart1 redpart3 1
bluepart3 redpart2 2
bluepart4 redpart2 2
...
and so on. I would like to write the nametags onto the blue/red squares, so that the user knows which is which.
Followup question: How can i generate a graph from this with the nodes partly marked blue/red? Kind of like this:
But with the nodes reflecting their bipartite nature. I am still a bit in the dark on this, mainly because i don't know how to tackle this with matplotlib. I am hoping for a few good suggestions on how to visualize this and maybe an example implementation that shows me the way.
Try using networkx. You can use it to display the graph with specific colors on the nodes and links to match your data.
Here's an example:
import itertools
import networkx as nx
import matplotlib.pyplot as plt
edgelist = [(u,v,(u+v)%2) for u,v in itertools.product(range(3),range(3,6))]
G = nx.Graph()
for u,v,t in edgelist:
G.add_edge(u,v,attr_dict={'t':t})
ecolors = tuple('g' if G[u][v]['t'] == 1 else 'm' for u,v in G.edges())
nx.draw_networkx(G,node_color='rrrccc',edge_color=ecolors)
plt.show()
Here is another NetworkX/Matplotlib idea
import random
import networkx as nx
from networkx.algorithms.bipartite import biadjacency_matrix
import matplotlib.pyplot as plt
# generate random bipartite graph, part 1: nodes 0-9, part 2: nodes 10-29
B = nx.bipartite_random_graph(10,20,0.25)
# add some random weights
for u,v in B.edges():
B[u][v]['weight']=random.randint(0,4)
# spring graphy layout
plt.figure(1)
pos = nx.spring_layout(B)
colors = [d['weight'] for (u,v,d) in B.edges(data=True)]
nx.draw(B,pos,node_color='#A0CBE2',edge_color=colors,width=4,edge_cmap=plt.cm.Blues,with_labels=False)
plt.savefig('one.png')
# simple bipartite layout
plt.figure(2)
pos = {}
for n in range(10):
pos[n]=(n*2,1)
for n in range(10,30):
pos[n]=(n-10,0)
nx.draw(B,pos,node_color='#A0CBE2',edge_color=colors,width=4,edge_cmap=plt.cm.Blues,with_labels=False)
plt.savefig('two.png')
# biadjacency matrix colormap
M = biadjacency_matrix(B,row_order=range(10),column_order=range(10,30))
plt.matshow(M,cmap=plt.cm.Blues)
plt.savefig('three.png')
plt.show()
What about doing a bipartite representation with color edges like this?
Following is the code that generated the image.
import matplotlib.pyplot as plt
def addconnection(i,j,c):
return [((-1,1),(i-1,j-1),c)]
def drawnodes(s,i):
global ax
if(i==1):
color='r'
posx=1
else:
color='b'
posx=-1
posy=0
for n in s:
plt.gca().add_patch( plt.Circle((posx,posy),radius=0.05,fc=color))
if posx==1:
ax.annotate(n,xy=(posx,posy+0.1))
else:
ax.annotate(n,xy=(posx-len(n)*0.1,posy+0.1))
posy+=1
ax=plt.figure().add_subplot(111)
set1=['Man1','Man2','Man3','Man4']
set2=['Woman1','Woman2','Woman3','Woman4','Woman5']
plt.axis([-2,2,-1,max(len(set1),len(set2))+1])
frame=plt.gca()
frame.axes.get_xaxis().set_ticks([])
frame.axes.get_yaxis().set_ticks([])
drawnodes(set1,1)
drawnodes(set2,2)
connections=[]
connections+=addconnection(1,2,'g')
connections+=addconnection(1,3,'y')
connections+=addconnection(1,4,'g')
connections+=addconnection(2,1,'g')
connections+=addconnection(4,1,'y')
connections+=addconnection(4,3,'g')
connections+=addconnection(5,4,'y')
for c in connections:
plt.plot(c[0],c[1],c[2])
plt.show()
To get something like what your are drawing in yEd
import matplotlib.pyplot as plt
COLOR1='r'
COLOR2='b'
def addconnection(i,j,c):
if(c==1):
plt.gca().add_patch( plt.Rectangle((j-0.1,-i-0.1),0.2,0.2,fc='y'))
if(c==2):
plt.gca().add_patch( plt.Circle((j,-i),radius=0.1,fc='y'))
def drawnodes(s,i):
global ax
if(i==1):
color=COLOR1
vx=1
vy=0
else:
color=COLOR2
vx=0
vy=1
step=1
for n in s:
posx=step*vx
posy=step*vy
plt.gca().add_patch( plt.Circle((posx,-posy),radius=0.1,fc=color))
ax.annotate(n,xy=(posx-len(n)*0.1,-posy+0.15))
step+=1
f=open('input.txt')
t=f.readlines()
t=map(lambda x: x.replace('(',' ').replace(')',' ').split(':'),t)
set1=set([])
set2=set([])
for x in t:
s=x[1].split()
set1.add(s[0])
set2.add(s[1])
set1=list(set1)
set2=list(set2)
dic={}
for e in zip(set1,xrange(1,len(set1)+1)): dic[(e[0],1)]=e[1]
for e in zip(set2,xrange(1,len(set2)+1)): dic[(e[0],2)]=e[1]
ax=plt.figure(figsize=(max(len(set1),len(set2))+1,max(len(set1),len(set2))+1)).add_subplot(111)
plt.axis([-1,max(len(set1),len(set2))+1,-max(len(set1),len(set2))-1,1])
frame=plt.gca()
frame.axes.get_xaxis().set_ticks([])
frame.axes.get_yaxis().set_ticks([])
drawnodes(set1,1)
drawnodes(set2,2)
for x in t:
s=x[1].split()
addconnection(dic[(s[0],1)],dic[(s[1],2)],int(x[2]))
plt.show()
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