2009-04-04 9 views
8

J'ai généré this dendrogram en utilisant les fonctions R hclust(), as.dendrogram() et plot.dendrogram().Comment est-ce que je colorie des bords ou trace des retraits correctement dans un dendrogramme de R?

J'ai utilisé la fonction dendrapply() et une fonction locale pour colorer les feuilles, ce qui fonctionne très bien.

J'ai les résultats d'un test statistique qui indiquent si un ensemble de noeuds (par exemple le groupe de « _+v\_stat5a\_01_ » et « _+v\_stat5b\_01_ » dans le coin inférieur droit de l'arbre) sont significatifs ou importants.

J'ai aussi une fonction locale que je peux utiliser avec dendrapply() qui trouve le noeud exact dans mon dendrogramme qui contient des feuilles significatives.

Je voudrais soit (suivant l'exemple):

  1. Couleur des bords qui se rejoignent "_+v\_stat5a\_01_" et "_+v\_stat5b\_01_"; ou,
  2. Dessiner un rect() autour de "_+v\_stat5a\_01_" et "_+v\_stat5b\_01_"

J'ai la fonction locale suivant (les détails des "noeuds-en-leafList-match-nœuds-en-clusterList" état aren « t importante, mais il met en évidence des nœuds importants):

markSignificantClusters <<- function (n) { 
    if (!is.leaf(n)) { 
    a <- attributes(n) 
    leafList <- unlist(dendrapply(n, listLabels)) 
    for (clusterIndex in 1:length(significantClustersList[[1]])) { 
     clusterList <- unlist(significantClustersList[[1]][clusterIndex]) 
     if (nodes-in-leafList-match-nodes-in-clusterList) { 
      # I now have a node "n" that contains significant leaves, and 
      # I'd like to use a dendrapply() call to another local function 
      # which colors the edges that run down to the leaves; or, draw 
      # a rect() around the leaves 
     } 
    } 
    } 
} 

De dans ce bloc if, j'ai essayé d'appeler dendrapply(n, markEdges), mais cela ne fonctionne pas:

markEdges <<- function (n) { 
    a <- attributes(n) 
    attr(n, "edgePar") <- c(a$edgePar, list(lty=3, col="red")) 
} 

Dans mon exemple idéal, les bords reliant "_+v\_stat5a\_01_" et "_+v\_stat5b\_01_" seraient en pointillé et de couleur rouge.

J'ai également essayé d'utiliser rect.hclust() dans ce bloc if:

ma <- match(leafList, orderedLabels) 
rect.hclust(scoreClusterObj, h = a$height, x = c(min(ma), max(ma)), border = 2) 

Mais le résultat ne fonctionne pas avec dendrogrammes horizontal (à savoir de Dendrogrammes avec des étiquettes horizontales). Here is an example (notez la bande rouge dans le coin inférieur droit). Quelque chose n'est pas correct sur les dimensions de ce que rect.hclust() génère, et je ne sais pas comment cela fonctionne, pour pouvoir écrire ma propre version.

J'apprécie tout conseil pour obtenir edgePar ou rect.hclust() pour fonctionner correctement, ou pour être en mesure d'écrire mon propre rect.hclust() équivalent.

MISE À JOUR

Depuis posant cette question, j'ai utilisé getAnywhere(rect.hclust()) pour obtenir le code fonctionnel qui calcule les paramètres et dessine l'objet rect. J'ai écrit une version personnalisée de cette fonction pour gérer les feuilles horizontales et verticales, et appelez-le avec dendrapply().

Cependant, il existe une sorte d'effet de découpe qui supprime une partie du rect.Pour les feuilles horizontales (feuilles qui sont dessinées sur le côté droit de l'arbre), le bord le plus à droite du rect disparaît ou est plus mince que la largeur de la bordure des trois autres côtés du rect. Pour les feuilles verticales (feuilles qui sont dessinées sur le bas de l'arbre), le bord le plus bas du rect souffre du même problème d'affichage. Ce que j'avais fait pour marquer les grappes significatives est de réduire la largeur du rect de sorte que je rende une bande rouge verticale entre les pointes des arêtes et les étiquettes de feuilles (horizontales). Ceci élimine le problème d'écrêtage, mais introduit un autre problème, en ce sens que l'espace entre les pointes de bord du cluster et les étiquettes de feuille ne fait que six pixels de large, sur lequel je n'ai pas beaucoup de contrôle. Cela limite la largeur de la bande verticale.

Le problème plus grave est que le x -Coordonner qui marque lorsque la bande verticale peut se loger entre les deux éléments change en fonction de la largeur de l'arbre plus grand (par["usr"]), qui à son tour dépend de la façon dont la hiérarchie de l'arborescence se termine être structuré.

J'ai écrit une "correction" ou, mieux nommé, un hack pour ajuster cette valeur x et la largeur rect pour les arbres horizontaux. Cela ne fonctionne pas toujours de manière cohérente, mais pour les arbres que je produis, il semble ne pas trop s'approcher (ou se chevaucher) des bords et des étiquettes.

Finalement, une meilleure solution serait de trouver comment dessiner le rect afin qu'il n'y ait pas d'écrêtage. Ou un moyen cohérent de calculer la position spécifique x entre les arêtes d'arbre et les étiquettes pour n'importe quel arbre donné, de manière à centrer et à dimensionner correctement la bande.

Je serais également très intéressé par une méthode pour annoter des bords avec des couleurs ou des styles de lignes.

+0

Eh bien, j'ai écrit une fonction rect.dendrogram dans le paquetage dendextend.Il y a aussi une fonction pour colorier les branches en fonction des étiquettes qu'elles contiennent appelées 'branches_attr_by_labels'. –

Répondre

2

Vous avez donc posé environ cinq questions (5 +/- 3). En ce qui concerne l'écriture de votre propre fonction rect.hclust, la source est dans library/stats/R/identify.hclust.R si vous voulez le voir.

Je pris un rapide coup d'œil à moi-même et je ne sais pas ce fait ce que je pensais qu'il a fait à la lecture de votre description - il semble dessiner plusieurs rectangles, également, le sélecteur x semble être dur dans le code Séparez les étiquettes horizontalement (ce qui n'est pas ce que vous voulez et il n'y a pas de y).

Je serai de retour, mais en attendant vous pourriez (en plus de regarder la source) essayer de faire plusieurs rect.hclust avec différentes couleurs border= et différentes valeurs h= pour voir si un modèle de défaillance émerge.

Mise à jour

Je n'ai pas eu beaucoup de chance à ce piquer soit. Un des arguments possibles pour le découpage serait de remplir les étiquettes avec des espaces de fin, puis d'amener légèrement le bord de votre rectangle (l'idée étant que le simple fait d'introduire le rectangle le ferait sortir de la zone de découpage mais écraserait le extrémités des étiquettes).

Une autre idée serait de remplir le rectangle avec une couleur translucide (faible alpha), en faisant une zone ombragée plutôt que d'une boîte de délimitation.