2009-04-04 21 views
8

Ho generato this dendrogram utilizzando le funzioni R hclust(), as.dendrogram() e plot.dendrogram().Come posso colorare i bordi o disegnare correttamente i rec in un dendogramma R?

Ho usato la funzione dendrapply() e una funzione locale per colorare le foglie, che funziona bene.

devo risultati di un test statistico che indicano se un insieme di nodi (ad esempio cluster di "_+v\_stat5a\_01_" e "_+v\_stat5b\_01_" nell'angolo inferiore destro dell'albero) sono significative o importanti.

Ho anche una funzione locale che posso utilizzare con dendrapply() che trova il nodo esatto nel mio dendrogramma che contiene foglie significative.

desidero o (seguendo l'esempio):

  1. colori i bordi che uniscono "_+v\_stat5a\_01_" e "_+v\_stat5b\_01_"; o,
  2. Disegnare una rect() intorno "_+v\_stat5a\_01_" e "_+v\_stat5b\_01_"

Ho la seguente funzione locale (i dettagli dei "nodi-in-leafList match-nodi-in-clusterList" condizione aren 't importante, ma che mette in luce i nodi significativi):

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 
     } 
    } 
    } 
} 

da questa if blocco, ho provato a chiamare dendrapply(n, markEdges), ma questo non ha funzionato:

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

Nel mio esempio ideale, i bordi che collegano "_+v\_stat5a\_01_" e "_+v\_stat5b\_01_" sarebbero tratteggiati e di colore rosso.

ho anche provato ad utilizzare rect.hclust() all'interno di questo blocco if:

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

Ma il risultato non funziona con dendrogrammi orizzontali (cioè dendrogrammi con etichette orizzontali). Here is an example (notare la striscia rossa nell'angolo in basso a destra). Qualcosa non è corretto sulle dimensioni di ciò che genera rect.hclust(), e non so come funziona, per essere in grado di scrivere la mia versione.

Apprezzo qualsiasi suggerimento per ottenere edgePar o rect.hclust() per funzionare correttamente, o per essere in grado di scrivere il mio equivalente rect.hclust().

UPDATE

Da questa domanda, ho usato getAnywhere(rect.hclust()) per ottenere il codice funzionale che calcola i parametri e disegna l'oggetto rect. Ho scritto una versione personalizzata di questa funzione per gestire le foglie orizzontali e verticali e chiamarla con dendrapply().

Tuttavia, è presente un tipo di effetto di ritaglio che rimuove parte dello rect.Per le foglie orizzontali (foglie disegnate sul lato destro dell'albero), il bordo più a destra di rect scompare o è più sottile della larghezza del bordo degli altri tre lati di rect. Per le foglie verticali (foglie disegnate sul fondo dell'albero), il bordo inferiore dello rect soffre dello stesso problema di visualizzazione.

Ciò che avevo fatto per contrassegnare cluster significativi è ridurre la larghezza dello rect in modo da rendere una striscia rossa verticale tra le punte dei bordi del cluster e le etichette foglia (orizzontali).

Questo elimina il problema di ritaglio, ma introduce un altro problema, in quanto lo spazio tra i bordi del bordo del cluster e le etichette foglia è largo solo sei pixel, cosa su cui non ho molto controllo. Questo limita la larghezza della striscia verticale.

Il problema peggiore è che il -coordinate x che segna dove la striscia verticale può andare bene tra i due elementi cambierà in base alla larghezza della struttura più grande (par["usr"]), che a sua volta dipende da come la gerarchia della struttura finisce essere strutturato.

Ho scritto una "correzione" o, meglio definita, un trucco per regolare questo valore x e la larghezza rect per alberi orizzontali. Non sempre funziona in modo coerente, ma per gli alberi che sto creando sembra non avvicinarsi troppo (o sovrapporsi) ai bordi e alle etichette.

In definitiva, una soluzione migliore sarebbe scoprire come disegnare il rect in modo che non ci sia il clipping. O un modo coerente per calcolare la specifica posizione x tra i bordi dell'albero e le etichette per ogni albero dato, in modo da centrare e ridimensionare correttamente la striscia.

Sarei anche molto interessato a un metodo per annotare i bordi con colori o stili di linea.

+0

Bene, ho scritto una funzione rect.dendrogram nel pacchetto dendextend.C'è anche una funzione per colorare i rami in base alle etichette che contengono chiamati 'branches_attr_by_labels'. –

risposta

2

Quindi hai effettivamente chiesto cinque domande (5 +/- 3). Per quanto riguarda la scrittura della propria funzione rect.hlike, la sorgente è in library/stats/R/identify.hclust.R se si vuole guardarla.

ho preso una rapida occhiata a me stesso e non sono sicuro che fa quello che ho pensato che ha fatto dalla lettura tua descrizione - sembra essere il disegno più rettangoli, inoltre, il selettore x sembra essere codificato difficile segregare i tag orizzontalmente (che non è quello che vuoi e non c'è).

Torno, ma nel frattempo si potrebbe (oltre a guardare alla fonte) prova a fare rect.hclust multipla con diversi colori e diversi border=h= valori per vedere se un modello di fallimento emerge.

Aggiornamento

non ho avuto molta fortuna frugando in questa operazione.

Un possibile kludge per il ritaglio sarebbe quello di riempire le etichette con spazi finali e quindi di portare leggermente il bordo del rettangolo (l'idea è che basta portare il rettangolo per farlo uscire dalla zona di ritaglio ma sovrascrivere il estremità delle etichette).

Un'altra idea sarebbe quella di riempire il rettangolo con un colore traslucido (basso alfa), creando un'area ombreggiata anziché un rettangolo di selezione.