2017-05-31 103 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