2016-04-25 17 views
2

Ich verwende pheatmap, um eine Heatmap von Werten zu erstellen und möchte die Legende mit den Einheiten der z-Werte in der Matrix beschriften. In diesem Beispiel würde ich gerne sagen, dass die Spitze der Legende Temperatur [° C] bedeutet. Ich habe die guidelines here für pheatmap gelesen, und es scheint, dass die einzige Manipulation der Legende darin besteht, eine Liste von Standardzahlen hinzuzufügen, die anstelle der Skala angezeigt werden. Ich kann keine Option sehen, um einen Legendentitel per se hinzuzufügen.R - Legende Titel oder Einheiten bei Verwendung von Pheatmap

Hier ist ein generischer Code-Block, um eine Matrix und einen Plot mit pheatmap zu erzeugen. Ich würde wirklich jeden Hinweis schätzen, wie man der Legende einen Titel hinzufügt.

test <- matrix(rexp(200, rate=.1), ncol=20) 
colnames(test) = paste("Room", 1:20, sep = "") 
rownames(test) = paste("Building", 1:10, sep = "") 

pheatmap(test, legend = TRUE, cluster_rows = FALSE, cluster_cols = FALSE) 

enter image description here

Antwort

5

OK so da jemand noch diese zu verantworten hat, ich Ihnen eine mögliche Option geben würde, wenn Sie unbedingt die pheatmap Funktion verwenden. Das ist viel einfacher zu ggplot tun verwenden, aber hier geht es:

Zuerst haben wir unser Grundstück gehen zu wollen, zu erzeugen, so dass wir alle die Handlung können Objekte eigenes Grundstück, mit einer bearbeiteten Legende zu schaffen.

#Edited to add in library names 
library(gtable) 
library(grid) 

#Starting with data and generating initial plot 
test <- matrix(rexp(200, rate=.1), ncol=20) 
colnames(test) = paste("Room", 1:20, sep = "") 
rownames(test) = paste("Building", 1:10, sep = "") 

p<-pheatmap(test, legend = TRUE, cluster_rows = FALSE, cluster_cols = FALSE) 



#Get grobs we want - will use these to create own plot later 
plot.grob <- p$gtable$grob[[1]] 
xlab.grob <- p$gtable$grob[[2]] 
ylab.grob <- p$gtable$grob[[3]] 
legend.grob <- p$gtable$grob[[4]] 

Nun, wenn wir unsere Objekte haben, wollen wir tatsächlich die Legende herunterschalten ein wenig Platz für den Titel zu machen.

#Shift both down by 1 inch 
legend.grob$children[[1]]$y <- legend.grob$children[[1]]$y - unit(0.85,"inches") 
legend.grob$children[[2]]$y <- legend.grob$children[[2]]$y - unit(0.85,"inches") 
legend.grob$children[[1]]$x <- legend.grob$children[[1]]$x + unit(0.4,"inches") 
legend.grob$children[[2]]$x <- legend.grob$children[[2]]$x + unit(0.4,"inches") 

Da wir Platz für die Legende gemacht haben, können wir jetzt die Legende textGrob erstellen und fügen Sie ihn in der Legende grobTree (nur Satz von grafischen Objekten in dem, was wir wollen, dass unsere Legende zu sein)

#New legend label grob 
leg_label <- textGrob("Temperature [°C]",x=0,y=0.9,hjust=0,vjust=0,gp=gpar(fontsize=10,fontface="bold")) 

#Add label to legend grob 
legend.grob2 <- addGrob(legend.grob,leg_label) 

Wenn Sie möchten, zu prüfen, was unsere Legende wie try aussehen:

grid.draw(legend.grob2) 

Jetzt brauchen wir eigentlich unser gtable Objekt zu bauen. Dazu verwenden wir ein ähnliches Layout (mit einigen Modifikationen) als das von der Funktion pheatmap erzeugte Plot. Beachten Sie auch, dass die pheatmap Funktion ein gtable Objekt erzeugt, das durch zugegriffen werden kann:

p$gtable 

Um die Breiten/Höhen von jedem der „Sektoren“ in unserem gtable Objekt alles, was wir tun müssen, um zu sehen sind:

p$gtable$heights 
p$gtable$widths 

Diese dienen als unsere Referenzwerte. Für eine grafische Darstellung try:

gtable_show_layout(p$gtable) 

der dieses Bild ergibt:

enter image description here

Ok, also jetzt, dass wir die Grobs haben wir wollen, alles, was wir tun müssen, um unsere gtable bauen basiert auf was wir sahen für die gtable von pheatmap gebaut. Einige Beispielcode ich geschrieben habe ist:

my_new_gt <- gtable(widths= unit.c(unit(0,"bigpts") + unit(5,"bigpts"), 
            unit(0,"bigpts"), 
            unit(1,"npc") - unit(1,"grobwidth",plot.grob) + unit(10,"bigpts") - max(unit(1.1,"grobwidth",plot.grob), (unit(12,"bigpts")+1.2*unit(1.1,"grobwidth",plot.grob))) + unit(5,"bigpts") - unit(3,"inches"), 
            unit(1,"grobwidth",ylab.grob) + unit(10,"bigpts"), 
            max(unit(1,"grobwidth",legend.grob2),unit(12,"bigpts")+1.2*unit(1.1,"grobwidth",legend.grob2)) + unit(1,"inches") , 
            max(unit(0,"bigpts"),unit(0,"bigpts")) 
            ), 



        height = unit.c(unit(0,"npc"), 
            unit(5,"bigpts"), 
            unit(0,"bigpts"), 
            unit(1,"npc") - unit(1,"grobheight",xlab.grob) + unit(15,"bigpts") - unit(0.2,"inches"), 
            unit(1,"grobheight",xlab.grob) + unit(15,"bigpts")  
        )) 

Schließlich können wir alle unsere Objekte zu unserem neuen gtable fügen Sie eine sehr ähnliche Darstellung, die der von pheatmap mit dem zusätzlichen Legendentitel erzeugt zu bekommen.

#Adding each grob to the appropriate spot 
gtable <- gtable_add_grob(my_new_gt,plot.grob,4,3) 
gtable <- gtable_add_grob(gtable,xlab.grob,5,3) 
gtable <- gtable_add_grob(gtable,ylab.grob,4,4) 
gtable <- gtable_add_grob(gtable,legend.grob2,4,5) 

grid.draw(gtable) 

Schließlich wird die erzeugte Ausgabe ist:

enter image description here

Hope this geholfen. Sie können mit den verschiedenen Größen herumspielen, um das Layout dynamischer zu gestalten, aber ich denke, das ist ein gutes Setup und bringt Ihnen, was Sie wollten - die Pheatmap mit einer Legende.

EDIT - ggplot Option:

Da ich empfohlen ggplot als Alternative hier einige Code, um es zu tun ist:

library(ggplot2) 
library(reshape) 
test <- as.data.frame(matrix(rexp(200, rate=.1), ncol=20)) 
colnames(test) = paste("Room", 1:20, sep = "") 
test$building = paste("Building", 1:10, sep = "") 

#Get the sorting right 
test$sort <- 1:10 

#Melting data so we can plot it with GGplot 
test.m <- melt(test,id.vars = c("building","sort")) 

#Resetting factors 
test.m$building <- factor(test.m$building, levels=(test.m$building)[order(test.m$sort)]) 

#Creating the plot itself 
plot <- ggplot(test.m,aes(variable,building)) + geom_tile(aes(fill=value),color = "white") + 
     #Creating legend 
     guides(fill=guide_colorbar("Temperature [°C]")) + 
     #Creating color range 
     scale_fill_gradientn(colors=c("skyblue","yellow","tomato"),guide="colorbar") + 
     #Rotating labels 
     theme(axis.text.x = element_text(angle = 270, hjust = 0,vjust=-0.05)) 
plot 

die in diesem Plot erzeugt: Als

enter image description here

Sie können sehen, dass die ggplot2-Methode viel schneller ist. Alles, was Sie tun müssen, ist Ihre Daten in einen Datenrahmen zu konvertieren und dann zu schmelzen. Sobald das erledigt ist, können Sie die Legende Titel leicht ändern.

+0

Sorry für meine verspätete Antwort, aber vielen Dank für diese erstaunliche Antwort. Ihre Antwort ist so detailliert und hilft mir, pheatmap so viel besser zu verstehen! Ich wollte dich gerade den Unterschied zwischen ggplot und pheatmap fragen, aber du hast es schon beantwortet! Die eine Sache, die ich an pheatmap mag, ist, wie sie mit NA-Werten umgehen kann, indem sie sie als eine andere Farbe als die Skala aufträgt. Dies ist nützlich für mich, da es sich um einen Datensatz mit einigen NA-Werten handelt. Obwohl ich noch nicht mit ggplot ausprobiert habe. Nochmals vielen Dank. – alkey

3

MikeyMikes Antwort ist unglaublich; Ich habe auch viel gelernt, indem ich es gelesen habe.

Allerdings brauchte ich eine dumme, hässliche, 10 Sekunden Lösung:

test <- matrix(rexp(200, rate=.1), ncol=20) 
colnames(test) = paste("Room", 1:20, sep = "") 
rownames(test) = paste("Building", 1:10, sep = "") 

pheatmap(test, legend_breaks = c(10, 20, 30, 40, max(test)), 
main = "", legend_labels = c("10", "20", "30", "40", "title\n"), 
legend = TRUE, cluster_rows = FALSE, cluster_cols = FALSE) 

die in diesem Heatmap produziert:

enter image description here