2017-05-31 106 views
1

我试图从两个不同的距离矩阵创建树形图并对它们进行比较。我使用代码here作为起点,但问题是因为我使用了两个不同的矩阵,但使用了相同的聚类方法,所以我需要将两个不同的矩阵一起绘制以进行比较分析。我想知道是否有可能将每个正方形/节点的两半对角线分开以显示两个不同的距离矩阵。在同一图上绘制两个距离矩阵?

此图片代表我瞄准结果: enter image description here

这里是我的代码:

from sklearn import preprocessing 
from sklearn.neighbors import DistanceMetric 
import pandas as pd 
import numpy as np 
from ete3 import Tree 
from sklearn.metrics.pairwise import cosine_similarity 
from sklearn.metrics.pairwise import cosine_distances 
import scipy 
import pylab 
import scipy.cluster.hierarchy as sch 
import scipy.spatial.distance as sd 
import random 
#g[n] is a one dimensional array containing datapoints 
g1 = random.sample(range(30), 5) 
g2 = random.sample(range(30), 5) 
g3 = random.sample(range(30), 5) 
g4 = random.sample(range(30), 5) 
g5 = random.sample(range(30), 5) 
g1 = np.array(g1) 
g2 = np.array(g2) 
g3 = np.array(g3) 
g4 = np.array(g4) 
g5 = np.array(g5) 
X = (g1,g2,g3,g4,g5) 
#Comparing between euclidean and cosine########################################### 
distanceC = cosine_distances(X) 
dist = DistanceMetric.get_metric('euclidean') 
distanceE = dist.pairwise(X) 
################################################################################## 

#Plots############################################################################ 

# 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.average(sd.squareform(distanceC)) 
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.average(sd.squareform(distanceE)) 
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'] 
distance = distance[idx1,:] 
distance = distance[:,idx2] 
im = axmatrix.matshow(distance, 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') 
################################################################################## 
+0

我已经删除了第二个问题。虽然我明白这里的代码示例有点“破碎”,但问题在于生成列表g1,g2 ... g5的代码有很多文件IO和处理操作,这些操作并不真正相关,但我仍然绑定用一个随机列表生成器代替它,它应该完成这项工作。 – Siddharth

回答

2

没有内置的方法来绘制图像组成的三角形,切割像素减半。

所以人们需要建立一些自定义热图。这可以使用三角形的PolyCollection完成。在下面的解决方案中,函数创建原点周围的三角形点,如果需要则旋转它们,并应用偏移量。遍历数组允许为每个点创建一个三角形。最后,所有这些三角形都收集到PolyCollection中。

然后,您可能会决定使用正常的imshowmatshow图作为其中一个阵列和其上的自定义三角形矩阵。

import matplotlib.pyplot as plt 
import matplotlib.collections as collections 
import numpy as np 

def triatpos(pos=(0,0), rot=0): 
    r = np.array([[-1,-1],[1,-1],[1,1],[-1,-1]])*.5 
    rm = [[np.cos(np.deg2rad(rot)), -np.sin(np.deg2rad(rot))], 
      [np.sin(np.deg2rad(rot)),np.cos(np.deg2rad(rot)) ] ] 
    r = np.dot(rm, r.T).T 
    r[:,0] += pos[0] 
    r[:,1] += pos[1] 
    return r 

def triamatrix(a, ax, rot=0, cmap=plt.cm.viridis, **kwargs): 
    segs = [] 
    for i in range(a.shape[0]): 
     for j in range(a.shape[1]): 
      segs.append(triatpos((j,i), rot=rot)) 
    col = collections.PolyCollection(segs, cmap=cmap, **kwargs) 
    col.set_array(a.flatten()) 
    ax.add_collection(col) 
    return col 


A,B = np.meshgrid(range(5), range(4)) 
B*=4 

fig, ax=plt.subplots() 
im1 = ax.imshow(A) 
im2 = triamatrix(B, ax, rot=90, cmap="Reds") 

fig.colorbar(im1, ax=ax,) 
fig.colorbar(im2, ax=ax,) 

plt.show() 

Triangle heatmap

当然它也同样可以使用两种这些三角的矩阵

im1 = triamatrix(A, ax, rot=0, cmap="Blues") 
im2 = triamatrix(B, ax, rot=180, cmap="Reds") 
ax.set_xlim(-.5,A.shape[1]-.5) 
ax.set_ylim(-.5,A.shape[0]-.5) 

这也将需要手动设置轴界限。

+0

谢谢!这正是我正在寻找的。我现在在将方法与树状图结合时遇到了一些麻烦,即树叶没有与矩阵中相应的距离对齐。 – Siddharth

+0

对不起,我没有scikit-lern可用。你可以设置所有3个地块的蜱可见,并提供一个图像,从哪个人可以看到哪里出了问题? – ImportanceOfBeingErnest

+0

我很抱歉这个迟到的回复,我试着用代码多玩一点。我想问题是有两种不同类型的放置方法,(dendrograms的add_axes和distance matrix的add_subplot)。我得到的结果是奇怪的:http://imgur.com/a/AwJfi – Siddharth