Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i visualize a connection Matrix with Matplotlib?

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:

example

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:

graphexample

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.

like image 770
tarrasch Avatar asked Nov 28 '12 16:11

tarrasch


3 Answers

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()

Simple Example

like image 54
job Avatar answered Oct 14 '22 18:10

job


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()

enter image description here

enter image description here

enter image description here

like image 20
Aric Avatar answered Oct 14 '22 18:10

Aric


What about doing a bipartite representation with color edges like this?

Bipartite graph with different kinds of connections

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

Connection matrix

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()
like image 40
bcurcio Avatar answered Oct 14 '22 17:10

bcurcio