【问题标题】:How do i visualize a connection Matrix with Matplotlib?如何使用 Matplotlib 可视化连接矩阵?
【发布时间】:2012-11-16 13:51:43
【问题描述】:

我正在尝试可视化一个二分集问题的连接矩阵。我如何以最好的方式做到这一点?

我已经开始使用图形程序 yed:

圆圈描述了红色和蓝色之间的某种联系,而正方形则描述了另一种联系。红色和蓝色方块上都会有某种文字。

但是,使用 matplotlib 生成这个图形会更好,因为我想在附加数据的情况下即时生成这个图形。我将如何继续这样做? 我的数据看起来有点像这样:

数据:

name_blue name_red Connection Type
bluepart1 redpart1 1
bluepart1 redpart2 1
bluepart1 redpart3 1
bluepart3 redpart2 2 
bluepart4 redpart2 2
...

等等。我想将名称标签写在蓝色/红色方块上,以便用户知道哪个是哪个。

后续问题: 我如何从中生成一个图表,其中节点部分标记为蓝色/红色?有点像这样:

但是节点反映了它们的二分性。我对此仍然有些不知所措,主要是因为我不知道如何用 matplotlib 解决这个问题。我希望对如何可视化这一点提出一些好的建议,也许还有一个示例实现可以向我展示。

【问题讨论】:

  • 您应该将后续问题拆分为一个单独的问题。
  • 我尝试将图片粘贴到 n^2 个子图的网格中。然而,这并不是真正的 pythonic 或 matplotlib 这样做的方式。为我和其他需要这种可视化的人提供更好的解决方案将不胜感激。

标签: python graph matplotlib visualization


【解决方案1】:

尝试使用networkx。您可以使用它在节点和链接上以特定颜色显示图表以匹配您的数据。

这是一个例子:

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

【讨论】:

  • 一定会检查出来的。
【解决方案2】:

这是另一个 NetworkX/Matplotlib 的想法

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

【讨论】:

    【解决方案3】:

    用这样的颜色边缘进行二分表示怎么样?

    以下是生成图像的代码。

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

    要获得类似于您在 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()
    

    【讨论】:

    • 会接受,如果连接矩阵也在那里...... :)
    • @tarrasch 哦,我明白了。我不确定是否可以使用干净的图形表示,除非您知道集合很小,因为您将不得不绘制多个相互连接的派系。我用 matplotlib 画出了你用 yEd 制作的东西,我认为它最能显示这些信息并用代码修改了答案
    • 好的,你赢得了这个 :) 如果你能识别我的文件格式并转换它,我也会支持你:“Pair :(MAN DESC WOMAN DESC) type:1” 其中 MAN DESC 是节点的名称。我有一整个这样的文件。
    • @tarrasch 当然,为了简单起见,我假设您的描述不会包含空格或“:”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 2020-11-01
    相关资源
    最近更新 更多