2010-06-06 66 views
44

如何在Python中将一个树状图正确绘制在值矩阵的顶部,重新排列以适当反映聚类?一个例子是如下图所示:在python中绘制数据矩阵顶部的层次聚类结果

https://publishing-cdn.elifesciences.org/07103/elife-07103-fig6-figsupp1-v2.jpg

我用scipy.cluster.dendrogram让我的树状图和数据矩阵进行分层聚类。那么我怎样才能将数据绘制成一个矩阵,其中行被重新排序以反映由在特定阈值处切割树状图引起的聚类,并且将树状图与矩阵一起绘制?我知道如何在scipy中绘制树状图,但不知道如何用旁边的右侧比例尺来绘制数据的强度矩阵。

任何帮助,将不胜感激。

+0

这更是一个matplotlib问题,我已经将它重新标记了。 – dwf 2010-06-06 08:06:52

+0

可能的重复:http://stackoverflow.com/questions/2455761/reordering-matrix-elements-to-reflect-column-and-row-clustering-in-naiive-python – 2010-06-09 18:19:26

+4

请更新链接到图片。 – 2015-07-27 13:58:37

回答

85

这个问题没有定义矩阵很好:“矩阵的值”,“数据矩阵”。我假设你的意思是距离矩阵。换句话说,对称非负N×N距离矩阵D中的元素D_ij表示两个特征向量x_i和x_j之间的距离。那是对的吗?

如果是的话,那就试试这个(编辑2010年6月13日,以反映两个不同的树状图):

import scipy 
import pylab 
import scipy.cluster.hierarchy as sch 

# Generate random features and distance matrix. 
x = scipy.rand(40) 
D = scipy.zeros([40,40]) 
for i in range(40): 
    for j in range(40): 
     D[i,j] = abs(x[i] - x[j]) 

# Compute and plot first dendrogram. 
fig = pylab.figure(figsize=(8,8)) 
ax1 = fig.add_axes([0.09,0.1,0.2,0.6]) 
Y = sch.linkage(D, method='centroid') 
Z1 = sch.dendrogram(Y, orientation='right') 
ax1.set_xticks([]) 
ax1.set_yticks([]) 

# Compute and plot second dendrogram. 
ax2 = fig.add_axes([0.3,0.71,0.6,0.2]) 
Y = sch.linkage(D, method='single') 
Z2 = sch.dendrogram(Y) 
ax2.set_xticks([]) 
ax2.set_yticks([]) 

# Plot distance matrix. 
axmatrix = fig.add_axes([0.3,0.1,0.6,0.6]) 
idx1 = Z1['leaves'] 
idx2 = Z2['leaves'] 
D = D[idx1,:] 
D = D[:,idx2] 
im = axmatrix.matshow(D, aspect='auto', origin='lower', cmap=pylab.cm.YlGnBu) 
axmatrix.set_xticks([]) 
axmatrix.set_yticks([]) 

# Plot colorbar. 
axcolor = fig.add_axes([0.91,0.1,0.02,0.6]) 
pylab.colorbar(im, cax=axcolor) 
fig.show() 
fig.savefig('dendrogram.png') 

Dendrogram and distance matrix http://up.stevetjoa.com/dendrogram.png

祝你好运!让我知道你是否需要更多的帮助。


编辑:对于不同的颜色,调整cmap属性中imshow。示例请参阅scipy/matplotlib docs。该页面还介绍了如何创建自己的色彩映射。为了方便起见,我建议使用预先存在的色彩映射表。在我的例子中,我使用了YlGnBu


编辑:add_axessee documentation here)接受列表或元组:(left, bottom, width, height)。例如,(0.5,0,0.5,1)在图的右半部分添加Axes(0,0.5,1,0.5)在该图的上半部分添加Axes

为方便起见,大多数人可能使用add_subplot。我喜欢add_axes的控制权。请使用add_axes([left,bottom,width,height], frame_on=False)删除边框。 See example here.

+0

这是一个很好的问题。还有几个问题:如何显示顶部样本的聚类?如果矩阵是基于样本的基因,那么您已经在左侧显示了这些基因,但我想要将样本聚类在顶部。我怎样才能适当地调整轴来做到这一点?另外,如何将颜色图调整为从黄色到蓝色,并控制右侧的比例尺?非常感谢! – user248237dfsf 2010-06-13 23:26:39

+0

我上传了一张不同颜色的图。请参阅编辑。你能定义“基因”和“样本”吗?相似度是如何计算的?尽管如此,我还在矩阵之上添加了第二个树状图。希望你可以根据你的需要进行调整。 – 2010-06-14 00:29:09

+0

谢谢史蒂夫,那回答了我关于顶级树状图的问题。再简要说明一下:你如何设置add_axes的参数?我不确定你是如何挑选这些数值的。例如,我想删除树状图周围的框,并只显示树。如果这些是常规的subplots,我可以在subplot.ax.spines中的每个spine上设置“set_color(none)”。我可以在这里做同样的事吗? – user248237dfsf 2010-06-14 03:56:35

8

如果除矩阵和树状图之外还需要显示元素的标签,则可以使用以下代码,该代码显示旋转x标签并更改字体大小的所有标签以避免重叠x轴。它要求移动所述颜色条有空间用于y标签:

axmatrix.set_xticks(range(40)) 
axmatrix.set_xticklabels(idx1, minor=False) 
axmatrix.xaxis.set_label_position('bottom') 
axmatrix.xaxis.tick_bottom() 

pylab.xticks(rotation=-90, fontsize=8) 

axmatrix.set_yticks(range(40)) 
axmatrix.set_yticklabels(idx2, minor=False) 
axmatrix.yaxis.set_label_position('right') 
axmatrix.yaxis.tick_right() 

axcolor = fig.add_axes([0.94,0.1,0.02,0.6]) 

得到的结果是这样的(具有不同的色彩映射):

The result obtained is this: