離散熱圖
0.需求
今天在群里看到一個非常漂亮的熱圖,我以為是什么奇怪的新R包畫的重付,轉(zhuǎn)了一圈發(fā)現(xiàn)原來還是大名鼎鼎的ComplexHeatmap丫。今天的代碼都是在作者寫的書基礎(chǔ)上探索學習的凫乖,書在:https://jokergoo.github.io/ComplexHeatmap-reference/book/
這種圖和普通熱圖的不同點:
- 數(shù)據(jù)是離散型的确垫,與常規(guī)的數(shù)值型熱圖不同。
- 每行單獨配色帽芽,顏色逐行變化
- 左右兩邊都有文字
- 劃分的不同板塊有格子
1.學習普通的離散型熱圖
以前畫的熱圖無一例外都是連續(xù)型數(shù)值删掀,這次是離散型數(shù)據(jù)咯,矩陣里面只有四個取值导街,所以就只有四個顏色披泪。如果不指定的話,顏色就是隨機的:
rm(list = ls())
library(ComplexHeatmap)
library(RColorBrewer)
library(circlize)
discrete_mat = matrix(sample(letters[1:4], 100, replace = TRUE), 10, 10)
Heatmap(t(discrete_mat),
column_split = discrete_mat[, 1],
top_annotation = HeatmapAnnotation(group = discrete_mat[, 1]),
border = T)
請忽略配色
切割搬瑰、加邊框款票、加注釋這樣的操作,參數(shù)還是蠻好找的泽论。
編一個類似于上面那張圖的輸入數(shù)據(jù)艾少,畫畫看。每一行都是有重復(fù)值的不同向量翼悴,并且向量的取值數(shù)量都是有限的缚够。
sl = function(letter,n = sample(2:4,1),ncol = 100){
sample(paste0(letter,1:n),ncol,replace = T)
}
table(sl("a"))
##
## a1 a2 a3 a4
## 21 31 25 23
dat = t(sapply(letters[1:10], sl))
rownames(dat) = LETTERS[1:10]
colnames(dat) = paste0("M",1:ncol(dat))
dat[1:4,1:4]
## M1 M2 M3 M4
## A "a1" "a2" "a1" "a2"
## B "b2" "b2" "b2" "b2"
## C "c1" "c1" "c1" "c2"
## D "d2" "d1" "d2" "d3"
col_group = rep(c("C1","C2","C3"),times = c(30,40,30))
row_group = rep(c("x","y"),times = c(6,4))
Heatmap(dat, name = "mat",
top_annotation = HeatmapAnnotation(cluster = col_group),
left_annotation = rowAnnotation(foo1 = row_group),
column_split = col_group,
row_split = row_group,
border = T,show_column_names = F)
請忽略配色
2.自定義顏色
ComplexHeatmap有一個特點,如果你不指定配色的話,每次運行相同代碼出來的圖配色都不一樣哦谍椅,所以接下來自己定義顏色误堡。
這里用到一個函數(shù):colorRamp2,出自circlize包雏吭,可以根據(jù)你指定的幾個顏色锁施,生成一組漸變色。
# 主體熱圖的顏色
m = apply(dat,1,function(x){length(unique(x))})
col_fun = colorRamp2(breaks = seq(0, 1, length.out = 12),
colors = brewer.pal(12,"Set3"))
qz = sort(unique(as.character(dat)));length(qz)
## [1] 28
colors = col_fun(seq(0, 1, length.out = length(qz)))
names(colors) = qz
head(colors)
## a1 a2 b1 b2 b3 c1
## "#8DD3C7FF" "#BFE5BFFF" "#ECF7B7FF" "#F2EFBDFF" "#D8D3CDFF" "#C2B8D6FF"
# 注釋條的顏色
color_an = brewer.pal(length(unique(col_group)),"Dark2")
names(color_an) = unique(col_group)
color_an
## C1 C2 C3
## "#1B9E77" "#D95F02" "#7570B3"
#頂部注釋
top_annotation = HeatmapAnnotation(cluster = col_group,col = list(cluster = color_an),show_legend = F,show_annotation_name = F)
f = Heatmap(dat, col = colors,
top_annotation = top_annotation,
row_split = ifelse(row_group=="x",""," "), #這一句是為了隱藏行分組的名字
column_split = col_group,
show_heatmap_legend = F,
border = T,show_column_names = F,row_names_side = "left",
right_annotation = rowAnnotation(score = anno_text(1:nrow(dat)))
)
f
隱藏圖例了
3.自定義圖例
前面有個參數(shù)是show_heatmap_legend = F
思恐,show_legend = F
,是不顯示主體與注釋圖例的意思沾谜。這里之所以不顯示是為了自定義圖例。否則呢胀莹,主體熱圖的圖例就會全部放在一起基跑,不能按行來顯示哦。
# 主體熱圖的圖例
k = 1
lgd = list()
for(i in 1:10){
un = sort(unique(dat[i,]))
ti = rownames(dat)[i]
lgd[[i]] = Legend(seq(0, 1, length.out = length(un)), labels = un,
title = ti, legend_gp = gpar(fill =colors[k:(k+length(un)-1)]))
k = k + length(un)
}
# 注釋的圖例
cld = Legend(labels = c("a1","a2","a3"), title = "cluster",
legend_gp = gpar(fill = color_an))
# 把各個圖例合并在一起
p = packLegend(list = c(cld,lgd),
direction = "horizontal",gap = unit(0.6, "cm"))
draw(p)
全部的圖例哦
# 主體和圖例畫到一起
draw(f,heatmap_legend_list = p,heatmap_legend_side = "bottom")
收工