2010-03-16 3 views
24

Ich bin auf der Suche nach einer Möglichkeit, Clustering separat auf Matrixzeilen und dann auf seinen Spalten durchzuführen, ordnen Sie die Daten in der Matrix neu, um das Clustering widerzuspiegeln und alles zusammenzufassen . Das Clusterproblem ist leicht lösbar, ebenso die Erzeugung des Dendrogramms (zum Beispiel in this blog oder in "Programming collective intelligence"). Wie ich die Daten neu anordne, bleibt jedoch unklar.Matrixelemente neu gruppieren, um das Spalten- und Zeilenclustering in Naiv Python widerzuspiegeln

Schließlich bin ich auf der Suche nach einer Möglichkeit zur Erstellung von Grafiken ähnlich wie die unten mit naiven Python (mit einer "Standard" -Bibliothek wie numpy, matplotlib usw., aber ohne using R oder andere externe Tools).

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

Clarifications

Ich wurde gefragt, was ich von Neuordnungs gemeint. Wenn Sie Daten in einer Matrix zunächst nach Matrixzeilen gruppieren, kann jede Matrixzelle anhand ihrer Spalten durch die Position in den beiden Dendrogrammen identifiziert werden. Wenn Sie die Zeilen und die Spalten der ursprünglichen Matrix so neu anordnen, dass die Elemente, die sich in den Dendrogrammen nahe beieinander befinden, einander in der Matrix nahe kommen und dann Heatmap generieren, kann das Clustering der Daten für den Betrachter sichtbar werden (wie in der Abbildung oben)

+0

Was meinst du mit Nachbestellung? Tausche n benachbarte Zeilen/Spalten mit einem anderen n? –

+0

Sie möchten numpy/scipy verwenden, wenn Sie sicher mit Matrizen umgehen. Matplotlib ahmt auch Matlab gut nach. Hier ist ein Deal: Wenn Sie dies in Matlab tun können, können Sie es auch in scipy tun (trivial Syntax Unterschied, wenn vorhanden). –

+1

Ooh, +1 für das schöne Bild ;-) –

Antwort

36

Siehe meine recent answer, in Teilen unten kopiert, zu 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

Wow, nette Lösung Du machst Matplotlib einfach, was ich denke, ist eine ziemliche Leistung Aber wie fügen Sie dann die Beschriftungen zu den X- und Y-Achsen hinzu? Benötigen Sie Twinx und Twiny oder gibt es ein Einfachere Methode – conradlee

+1

Vielen Dank Ich liebe Matplotlib und ich benutze es sehr viel.Python hilft Ihnen Matplotlib und PyLab weiter zu erforschen.Um die Achsen der Entfernungsmatrix (Abbildung Mitte) Labels hinzuzufügen, können Sie die 'set_xticks' und 'set_xticklabels' Siehe http: // ma tplotlib.sourceforge.net/api/axes_api.html?highlight=set_xticklabels#matplotlib.axes.Axes.set_xticklabels –

5

Ich bin mir nicht sicher, vollständig zu verstehen, aber es scheint, Sie versuchen, jede Achse des Arrays basierend auf Arten der Dendrogrammindizes neu zu indizieren. Ich nehme an, dass davon ausgegangen wird, dass es in jeder Abzweigungsabgrenzung eine vergleichende Logik gibt. Wenn dies der Fall ist, würde dann diese Arbeit (?):

>>> 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_idxs und y_idxs sind die dendrogram indicies. a ist die unsortierte Matrix. xi und yi sind Ihre neuen Zeilen-/Spaltenarray-Indizes. a2 ist die sortierte Matrix, während x_idxs2 und y_idxs2 die neuen, sortierten Dendrogrammindizes sind. Dies setzt voraus, dass beim Erstellen des Dendrogramms eine 0 Zweigspalte/Zeile immer vergleichsweise größer/kleiner als ein 1 Zweig ist.

Wenn Ihre y_idxs und x_idxs keine Listen sind, sondern Nummernfelder sind, können Sie np.argsort auf ähnliche Weise verwenden.

+0

was genau macht * in "zip (* sortierte ..."? –

+0

wann immer ich 'zip (*', denke ich "transpose". Siehe hier für die Verwendung von '*' zum Entpacken : http://docs.python.org/tutorial/controlflow.html#unpacking-argument-lists – Paul

+0

und einige weitere Diskussion hier: http://StackOverflow.com/questions/19339/a-Transpose-Unzip-Function-in -python – Paul

2

Ich weiß, das auf das Spiel ist sehr spät, aber ich habe ein Plotten Objekt basierend auf dem Code von der Post auf dieser Seite. Es ist auf pip registriert, so installieren Sie müssen nur anrufen

pip install pydendroheatmap 

Check hier die Projekt Github-Seite: https://github.com/themantalope/pydendroheatmap

Verwandte Themen