2016-04-21 7 views
10

Ich versuche die Farben zu extrahieren, die im Clustering von circlize_dendrogram verwendet werden. Hier ist ein Beispiel-Codes:Extrahiere Clusterfarbe aus der Ausgabe von dendextend :: circlize_dendrogram()

library(magrittr) 
library(dendextend) 

cols <- c("#009000", "#FF033E", "#CB410B", "#3B444B", "#007FFF") 
dend <- iris[1:40,-5] %>% dist %>% hclust %>% as.dendrogram  

dend <- color_branches(dend, k = 5, col = cols) 
dend %<>% set("labels_col", value = cols, k= 5) 
dend %<>% set("labels_cex", .8) 
dend %<>% set("branches_lwd", 2) 

circlize_dendrogram(dend) 

enter image description here

Damit die tabellarisch Cluster extrahiert verwenden cutree(dend, k = 5). Gibt es eine Möglichkeit, die Farben der Cluster im Dendrogramm basierend auf dem cols zu extrahieren? Ich brauche es zum Einfügen einer Legende in das Diagramm mit dem grid Paket.

Beispiel, Legende: Cluster 1 - #009000; Cluster 2 - #FF033E; Cluster 3 - #CB410B; Cluster 4 - #3B444B; Cluster 5 - #007FFF. Das Problem mit der circlize_dendrogram ist die Reihenfolge der Farben für Cluster verwendet wird, ist anders.

Obwohl ich das manuell tun kann, wäre es effizient, wenn ich es automatisch machen kann. Und das ist möglich, wenn ich die Farben der Cluster extrahieren kann.

Antwort

8

Ok, hier ist eine sehr hacky Lösung. Ich bin überzeugt, dass es bessere gibt, aber das ist ein erster Stich, also ertragen Sie mit mir.

Die Idee ist, das dend Objekt (das ist eine Liste intern) für die jeweiligen Elementnamen (in diesem Fall nur die Zahlen) zu suchen und die entsprechende Farbe zu extrahieren, speichern Sie es in einem Datenrahmen und verwenden Sie dies für eine Legende .

# First we'll extract the elements and corresponding categories... 
categories <- cutree(dend, k = 5) 

# ... and save them in a data frame 
categories_df <- data.frame(elements = as.numeric(names(categories)), 
     categories = categories, 
     color = NA) 

# now here's a little function that extracts the color for each element 
# from the 'dend' object. It uses the list.search() function from the 
# 'rlist' package 

library(rlist) 

extract_color <- function(element_no, dend_obj) { 
    dend.search <- list.search(dend_obj, all(. == element_no)) 
    color <- attr(dend.search[[1]], "edgePar")$col 
    return(color) 
} 

# I use 'dplyr' to manipulate the data 
library(dplyr) 

categories_df <- categories_df %>% 
    group_by(elements) %>% 
    mutate(color = extract_color(elements, dend)) 

Jetzt gibt uns den folgenden Datenrahmen:

> categories_df 
Source: local data frame [40 x 3] 
Groups: elements [40] 

    elements categories color 
     (dbl)  (int) (chr) 
1   1   1 #CB410B 
2   2   1 #CB410B 
3   3   1 #CB410B 
4   4   1 #CB410B 
5   5   1 #CB410B 
6   6   2 #009000 
7   7   1 #CB410B 
8   8   1 #CB410B 
9   9   3 #007FFF 
10  10   1 #CB410B 
..  ...  ...  ... 

Wir können die diesen Rahmen zu einem Datum zusammenzufassen nur mit den Farben für die Kategorien, z.B.

legend_data <- categories_df %>% 
    group_by(categories) %>% 
    summarise(color = unique(color)) 

> legend_data 
Source: local data frame [5 x 2] 

    categories color 
     (int) (chr) 
1   1 #CB410B 
2   2 #009000 
3   3 #007FFF 
4   4 #FF033E 
5   5 #3B444B 

Jetzt ist es einfach, die Legende zu generieren:

circlize_dendrogram(dend) 
legend(-1.05, 1.05, legend = legend_data$categories, fill = legend_data$color, cex = 0.7) 

Welche gibt Ihnen:

enter image description here

Sie können cutree(dend, k = 5) verwenden, um zu bestätigen, dass die Zahlen für die Kategorie Farben entsprechen die Kategorie jedes Elements.

+0

Clever! Ich konnte es gestern lösen. Aber ich bin an anderen möglichen Lösungen interessiert. –

5

Neben Felix-Lösung, würde Ich mag meine eigene Antwort schreiben:

library(magrittr) 
library(grid) 
library(gridExtra) 
library(dendextend) 

cols <- c("#009000", "#FF033E", "#CB410B", "#3B444B", "#007FFF") 
dend <- iris[1:40,-5] %>% dist %>% hclust %>% as.dendrogram  

dend <- color_branches(dend, k = 5, col = cols) 
dend %<>% set("labels_col", value = cols, k= 5) 
dend %<>% set("labels_cex", .8) 
dend %<>% set("branches_lwd", 2) 

clust <- cutree(dend, k = 5) 
colors <- labels_colors(dend)[clust %>% sort %>% names] 
clust_labs <- colors %>% unique 

circlize_dendrogram(dend) 
grid.circle(x = .95, y = .9, r = .02, gp = gpar(fill = clust_labs[1])) 
grid.circle(x = .95, y = .85, r = .02, gp = gpar(fill = clust_labs[2])) 
grid.circle(x = .95, y = .8, r = .02, gp = gpar(fill = clust_labs[3])) 
grid.circle(x = .95, y = .75, r = .02, gp = gpar(fill = clust_labs[4])) 
grid.circle(x = .95, y = .7, r = .02, gp = gpar(fill = clust_labs[5])) 

grid.text(x = .95, y = .9, label = expression(bold(1)), gp = gpar(fontsize = 9, col = "white")) 
grid.text(x = .95, y = .85, label = expression(bold(2)), gp = gpar(fontsize = 9, col = "white")) 
grid.text(x = .95, y = .8, label = expression(bold(3)), gp = gpar(fontsize = 9, col = "white")) 
grid.text(x = .95, y = .75, label = expression(bold(4)), gp = gpar(fontsize = 9, col = "white")) 
grid.text(x = .95, y = .7, label = expression(bold(5)), gp = gpar(fontsize = 9, col = "white")) 
grid.text(x = .91, y = .8, label = "CLUSTERS", rot = 90, gp = gpar(fontsize = 9)) 

enter image description here

Verwandte Themen