web-dev-qa-db-fra.com

traçage des résultats du clustering hiérarchique au-dessus d'une matrice de données dans python

Comment puis-je tracer un dendrogramme juste au-dessus d'une matrice de valeurs, réorganisé de manière appropriée pour refléter le clustering, en Python? Un exemple est la figure suivante:

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

J'utilise scipy.cluster.dendrogram pour faire mon dendrogramme et effectuer un clustering hiérarchique sur une matrice de données. Comment puis-je tracer les données sous forme de matrice où les lignes ont été réorganisées pour refléter un regroupement induit par la coupe du dendrogramme à un seuil particulier, et avoir le dendrogramme tracé à côté de la matrice? Je sais comment tracer le dendrogramme en scipy, mais pas comment tracer la matrice d'intensité des données avec la barre d'échelle à côté.

Toute aide à ce sujet serait grandement appréciée.

49
user248237

La question ne définit pas très bien matrice : "matrice de valeurs", "matrice de données". Je suppose que vous voulez dire une matrice de distance . En d'autres termes, l'élément D_ij dans la matrice de distance symétrique N-par-N symétrique D désigne la distance entre deux vecteurs de caractéristiques, x_i et x_j. Est-ce exact?

Si oui, essayez ceci (édité le 13 juin 2010 pour refléter deux dendrogrammes différents):

import scipy
import pylab
import scipy.cluster.hierarchy as sch
from scipy.spatial.distance import squareform


# 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])

condensedD = squareform(D)

# 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(condensedD, method='centroid')
Z1 = sch.dendrogram(Y, orientation='left')
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(condensedD, 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')

Plot

Bonne chance! Faites-moi savoir si vous avez besoin de plus d'aide.


Modifier: pour différentes couleurs, ajustez l'attribut cmap dans imshow. Voir les scipy/matplotlib docs pour des exemples. Cette page décrit également comment créer votre propre palette de couleurs. Pour plus de commodité, je recommande d'utiliser une palette de couleurs préexistante. Dans mon exemple, j'ai utilisé YlGnBu.


Modifier: add_axes ( voir la documentation ici ) accepte une liste ou un tuple: (left, bottom, width, height). Par exemple, (0.5,0,0.5,1) Ajoute un Axes dans la moitié droite de la figure. (0,0.5,1,0.5) Ajoute un Axes dans la moitié supérieure de la figure.

La plupart des gens utilisent probablement add_subplot Pour sa commodité. J'aime add_axes Pour son contrôle.

Pour supprimer la bordure, utilisez add_axes([left,bottom,width,height], frame_on=False). Voir l'exemple ici.

92
Steve Tjoa

Si, en plus de la matrice et du dendrogramme, il est nécessaire d'afficher les étiquettes des éléments, le code suivant peut être utilisé, qui montre toutes les étiquettes tournant les étiquettes x et changeant la taille de la police pour éviter le chevauchement sur l'axe x. Il faut déplacer la barre de couleur pour avoir de l'espace pour les étiquettes 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])

Le résultat obtenu est le suivant (avec une carte de couleurs différente):

The result obtained is this:

8
Picarus