2010-03-16 13 views
24

我正在尋找一種方法來分別在矩陣行和列上執行聚類,重新排列矩陣中的數據以反映聚類並將它們放在一起。聚類問題很容易解決,樹狀圖創建也很容易解決(例如在this blog"Programming collective intelligence"中)。但是,如何重新排序數據仍然不清楚。最終,我正在尋找一種使用樸素Python(使用任何「標準」庫(如numpy,matplotlib等),但沒有using R或其他外部工具)創建類似於下圖的圖表。重新排序矩陣元素,以反映列和行聚類naiive python

dendogram http://www2.warwick.ac.uk/fac/sci/moac/currentstudents/peter_cock/r/heatmap/no_scaling.png

澄清

有人問我,我的意思的重新排序。當您首先按照矩陣行對矩陣中的數據進行聚類時,那麼通過其列可以通過兩個樹形圖中的位置來識別每個矩陣單元。如果您對原始矩陣的行和列進行重新排序,使得樹狀圖中彼此靠近的元素在矩陣中彼此靠近,然後生成熱圖,則數據的聚類對於觀察者可能變得明顯(如上圖所示)

+0

你說的重新排序是什麼意思?用另一個n交換n個相鄰行/列? – 2010-03-16 15:45:21

+0

你想在處理矩陣時使用numpy/scipy。 Matplotlib也很好地模擬了Matlab。這是一個交易:如果你可以在Matlab中做到這一點,你也可以在scipy中做到這一點(如果有的話,簡單的語法差異)。 – 2010-03-16 15:50:22

+1

哦,+1的漂亮圖片;-) – 2010-03-21 16:58:27

回答

36

查看我的recent answer,部分複製到this related question

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

# Generate 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 dendrogram. 
fig = pylab.figure() 
axdendro = fig.add_axes([0.09,0.1,0.2,0.8]) 
Y = sch.linkage(D, method='centroid') 
Z = sch.dendrogram(Y, orientation='right') 
axdendro.set_xticks([]) 
axdendro.set_yticks([]) 

# Plot distance matrix. 
axmatrix = fig.add_axes([0.3,0.1,0.6,0.8]) 
index = Z['leaves'] 
D = D[index,:] 
D = D[:,index] 
im = axmatrix.matshow(D, aspect='auto', origin='lower') 
axmatrix.set_xticks([]) 
axmatrix.set_yticks([]) 

# Plot colorbar. 
axcolor = fig.add_axes([0.91,0.1,0.02,0.8]) 
pylab.colorbar(im, cax=axcolor) 

# Display and save figure. 
fig.show() 
fig.savefig('dendrogram.png') 

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

+1

哇,很好的解決方案,你讓matplotlib看起來很簡單,我認爲這是一個很棒的技術,但是你怎樣才能把標籤添加到x和y軸上呢?你需要使用twinx和twiny,還是有一個更直接的方法 – conradlee 2011-09-28 16:04:38

+1

Thank you。我喜歡matplotlib,我使用它很多。iPython可以幫助你進一步探索matplotlib和pylab。爲距離矩陣的軸添加標籤(圖中心),你可以使用'set_xticks'和'set_xticklabels'。參見http:// ma tplotlib.sourceforge.net/api/axes_api.html?highlight=set_xticklabels#matplotlib.axes.Axes.set_xticklabels – 2011-09-28 18:58:21

5

我不確定是否完全理解,但看起來您正試圖根據樹狀圖標記的種類重新對數組中的每個軸進行索引。我想這是假定每個分支劃分都有一些比較邏輯。如果是這樣的話,那麼將這項工作(?):

>>> x_idxs = [(0,1,0,0),(0,1,1,1),(0,1,1),(0,0,1),(1,1,1,1),(0,0,0,0)] 
>>> y_idxs = [(1,1),(0,1),(1,0),(0,0)] 
>>> a = np.random.random((len(x_idxs),len(y_idxs))) 
>>> x_idxs2, xi = zip(*sorted(zip(x_idxs,range(len(x_idxs))))) 
>>> y_idxs2, yi = zip(*sorted(zip(y_idxs,range(len(y_idxs))))) 
>>> a2 = a[xi,:][:,yi] 

x_idxsy_idxs是樹狀indicies。 a是未排序的矩陣。 xiyi是您的新行/列陣列標記。 a2是排序矩陣,而x_idxs2y_idxs2是新的排序樹狀圖標記。這假設當樹形圖被創建時,分支列/行總是比1分支更大/更小。

如果你的y_idxs和x_idxs不是列表,而是numpy數組,那麼你可以用類似的方式使用np.argsort

+0

「zip(* sorted ...」)做什麼? – 2010-03-24 07:29:25

+0

每當我看到'zip(*',我認爲是「轉置」。 請參閱這裏瞭解使用'*'進行拆包:http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists – Paul 2010-03-25 02:30:48

+0

和一些更多的討論在這裏:http://stackoverflow.com/questions/19339/a-transpose-unzip-function-in -python – Paul 2010-03-25 02:39:48