R - название легенды или единицы измерения при использовании Pheatmap
Я использую pheatmap для создания тепловой карты значений и хотел бы обозначить легенду единицами значений z в матрице. В этом примере я хотел бы, чтобы верхняя часть легенды говорила о температуре [°C]. Я прочитал рекомендации для pheatmap, и кажется, что единственной манипуляцией над легендой является добавление списка номеров по умолчанию для отображения вместо шкалы. Я не вижу никакой возможности добавить заголовок легенды как таковой.
Вот общий блок кода для генерации матрицы и графика с использованием pheatmap. Буду очень признателен за советы о том, как добавить заголовок к легенде.
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)
3 ответа
Хорошо, так как кто-то еще не ответил на этот вопрос, я дам вам один из возможных вариантов, если вам абсолютно необходимо использовать функцию pheatmap. Это намного проще сделать с помощью ggplot, но здесь это так:
Сначала мы захотим сгенерировать наш график, чтобы мы могли использовать все объекты графика для создания собственного графика с отредактированной легендой.
#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]]
Теперь, когда у нас есть наши объекты, мы действительно хотим немного сместить легенду, чтобы освободить место для названия.
#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")
Поскольку мы освободили место для легенды, теперь мы можем создать легенду textGrob и добавить ее в легенду grobTree (просто набор графических объектов в том виде, в котором мы хотим, чтобы наша легенда была)
#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)
Если вы хотите проверить, как будет выглядеть наша легенда, попробуйте:
grid.draw(legend.grob2)
Теперь нам нужно построить наш gtable объект. Для этого мы будем использовать похожий макет (с некоторыми изменениями), как график, сгенерированный функцией pheatmap. Также обратите внимание, что функция pheatmap генерирует объект gtable, к которому можно получить доступ:
p$gtable
Чтобы увидеть ширину / высоту каждого из "секторов" в нашем объекте gtable, все, что нам нужно сделать, это:
p$gtable$heights
p$gtable$widths
Они будут служить нашими справочными значениями. Для более графического отображения попробуйте:
gtable_show_layout(p$gtable)
Что дает это изображение:
Хорошо, теперь, когда у нас есть нужные нам гробы, все, что нам нужно сделать, это построить наш gtable на основе того, что мы видели для gtable, созданного pheatmap. Вот пример кода, который я написал:
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")
))
Наконец, мы можем добавить все наши объекты в наш новый gtable, чтобы получить график, очень похожий на график, сгенерированный pheatmap с добавленным заголовком легенды.
#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)
Наконец сгенерированный вывод:
Надеюсь, это помогло. Вы можете поиграть с различными размерами, чтобы попытаться сделать макет более динамичным, но я думаю, что это хорошая настройка и она дает вам то, что вы хотели - pheatmap с легендой.
РЕДАКТИРОВАТЬ - опция ggplot:
Поскольку я рекомендовал ggplot в качестве альтернативы, вот код для этого:
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
Который производит этот сюжет:
Как видите, метод ggplot2 намного быстрее. Все, что вам нужно сделать, это преобразовать ваши данные в массив данных, а затем расплавить их. Как только это будет сделано, вы можете легко изменить названия легенд.
Ответ MikeyMike невероятен; Я также многому научился, читая это.
Однако мне понадобилось тупое, некрасивое 10-секундное решение:
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)
Который производит эту тепловую карту:
Еще одно быстрое решение — просто заменитьpheatmap::pheatmap
с, а затем добавьтеheatmap_legend_param
аргумент, поддержанныйComplexHeatmap::pheatmap
:
ComplexHeatmap::pheatmap(test, legend = TRUE, cluster_rows = FALSE, cluster_cols = FALSE, heatmap_legend_param = list(title = "title", at = c(10,20,30,40)))