熱圖(Heatmap)是矩陣類(lèi)型數(shù)據(jù)最為常用的可視化方法,在生物學(xué)領(lǐng)域常用于各種組學(xué)數(shù)據(jù)的可視化,例如基因表達(dá)量數(shù)據(jù)凡傅、物種豐度分布、表觀遺傳信號(hào)數(shù)據(jù)等肠缔,我們前面也介紹過(guò)普通的熱圖繪制方法夏跷,例如pheatmap以及環(huán)形熱圖gheatmap等。但是明未,現(xiàn)如今多組學(xué)數(shù)據(jù)不斷涌現(xiàn)槽华, 現(xiàn)有的R語(yǔ)言包例如 gplots、pheatmap趟妥、ggplot2繪制熱圖的功能較為單一猫态,已無(wú)法滿足大家從多個(gè)維度、對(duì)多類(lèi)型數(shù)據(jù)更加充分可視化的需求披摄,例如下面的圖亲雪。ComplexHeatmap 由德國(guó)國(guó)家腫瘤疾病中心顧顧祖光博士開(kāi)發(fā),該R包正如其名一樣復(fù)雜疚膊,但是其繪制熱圖功能卻堪稱(chēng)全面义辕。所以我們也陸續(xù)學(xué)習(xí)一下這個(gè)包的功能和應(yīng)用。
=========安裝=======
library(devtools)
# 檢查熱圖包寓盗,沒(méi)有則通過(guò)github安裝最新版
if (!require("ComplexHeatmap"))
install_github("jokergoo/ComplexHeatmap")
# ComplexHeatmap依賴關(guān)系
if (!require("circlize"))
install_github("jokergoo/circlize")
# 用于繪制矩陣列方向上的層次聚類(lèi)結(jié)果
if (!require("dendextend"))
install.packages('dendextend')
# 加載包
library(ComplexHeatmap)
library(circlize)
library(dendextend)
=========測(cè)試==========
生成一組測(cè)試數(shù)據(jù):
nr1 = 4; nr2 = 8; nr3 = 6; nr = nr1 + nr2 + nr3
nc1 = 6; nc2 = 8; nc3 = 10; nc = nc1 + nc2 + nc3
mat = cbind(rbind(matrix(rnorm(nr1*nc1, mean = 1,? sd = 0.5), nr = nr1),
matrix(rnorm(nr2*nc1, mean = 0,? sd = 0.5), nr = nr2),
matrix(rnorm(nr3*nc1, mean = 0,? sd = 0.5), nr = nr3)),
rbind(matrix(rnorm(nr1*nc2, mean = 0,? sd = 0.5), nr = nr1),
matrix(rnorm(nr2*nc2, mean = 1,? sd = 0.5), nr = nr2),
matrix(rnorm(nr3*nc2, mean = 0,? sd = 0.5), nr = nr3)),
rbind(matrix(rnorm(nr1*nc3, mean = 0.5, sd = 0.5), nr = nr1),
matrix(rnorm(nr2*nc3, mean = 0.5, sd = 0.5), nr = nr2),
matrix(rnorm(nr3*nc3, mean = 1,? sd = 0.5), nr = nr3))
)
mat = mat[sample(nr, nr), sample(nc, nc)] # 打亂數(shù)據(jù)
rownames(mat) = paste0("row", seq_len(nr)) # 行命名
colnames(mat) = paste0("column", seq_len(nc)) # 列命名
這樣子一組簡(jiǎn)單的測(cè)試數(shù)據(jù)就準(zhǔn)備好了:
Heatmap(mat)? ?#生成一個(gè)最基本的heatmap
從默認(rèn)結(jié)果來(lái)看:這個(gè)包中最重要的函數(shù)Heatmap()繪制一張簡(jiǎn)單的熱圖终息,默認(rèn)參數(shù)下,會(huì)生成圖例贞让、行列名并對(duì)行列分別聚類(lèi)周崭,聚類(lèi)方法用complete層次聚類(lèi)方法。
下面我們開(kāi)始美化喳张,比如控制著色续镇。
比如我們相對(duì)列的聚類(lèi)樹(shù)按cluster著色,首先需要分成不同的cluster销部。
# 層次聚類(lèi)
column_dend = as.dendrogram(hclust(dist(t(mat))))? ? #獲得列進(jìn)化樹(shù)信息
# 分支著色
column_dend = color_branches(column_dend, k = 3)??#分成3個(gè)分支摸航,進(jìn)行不同顏色著色
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3? # 列分割數(shù)
? ? ? ? )
依據(jù)前面我們的列指定信息制跟,可以看出列的聚類(lèi)樹(shù)分成了3個(gè)顏色。column_split則把整個(gè)圖按列分成了3個(gè)部分酱虎。
對(duì)于長(zhǎng)度的控制雨膨,由于ComplexHeatmap基于grid繪圖框架,所以凡是量化長(zhǎng)度的參數(shù)都需要用unit()函數(shù)制定读串,例如下面的row_dend_width聊记,可以看出在對(duì)行聚類(lèi)樹(shù)的寬度的控制。
p1<-Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? #column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? )
p1
p2<-Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? #column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(10, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? )
p2
另外恢暖,ComplexHeatmap包的一個(gè)主要優(yōu)點(diǎn)是它支持按行和列拆分熱圖以更好地對(duì)特征進(jìn)行分組排监,便于突出顯示各組的信息。以下參數(shù)控制拆分:row_km, row_split, column_km, column_split杰捂。比如上面我們用column_split就是把列分成了3個(gè)部分舆床。row_km和column_km是按照 k-means方法分割,就如我們上述指定的column方法是按距離分割嫁佳,這是兩個(gè)不一樣的分割算法挨队。而row_split或者column_split可以設(shè)置為分類(lèi)向量或數(shù)據(jù)框,從分割算法來(lái)看是和默認(rèn)的距離算法是一致的蒿往。
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? row_km = 2 # 行k-means聚類(lèi)的類(lèi)別數(shù)
? ? ? ? )
下圖就是把行按kmeans分成了2類(lèi)瞒瘸。
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 2,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? row_split = rep(c("A", "B"), 9), # 行分割后的命名
? ? ? ? #row_km = 2 # 行k-means聚類(lèi)的類(lèi)別數(shù)
? ? ? ? )
這個(gè)是用row_split的方式,rep(c("A", "B"), 9)相當(dāng)于生成了ABAB...這樣子的數(shù)據(jù)框熄浓,然后A的列放在一起情臭,B的列放在一起。從而把row分成了2個(gè)部分赌蔑。
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? #row_split = rep(c("A", "B"), 9), # 行分割后的命名
? ? ? ? #row_km = 2 # 行k-means聚類(lèi)的類(lèi)別數(shù)
? ? ? ? row_split = data.frame(rep(c("A", "B"), 9), rep(c("C", "D"), each = 9))
? ? ? ? )
這樣子就是生成了一個(gè)更復(fù)雜的數(shù)據(jù)框俯在,生成了兩列,但是unique的數(shù)據(jù)的話有A.C A.D B.C B.D所以按unique的屬性分成了4不部分娃惯。
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? row_split = rep(c("A", "B"), 9), # 行分割后的命名
? ? ? ? row_km = 2 # 行k-means聚類(lèi)的類(lèi)別數(shù)
? ? ? ? )
通過(guò)兩種分割方法一起用跷乐,就相當(dāng)于有了2個(gè)屬性,一個(gè)是AB屬性框的分割趾浅,一個(gè)是kmeans的分割愕提。所以2*2就是4個(gè)屬性,分成了4個(gè)部分皿哨。
Heatmap(mat, name = "mat",
? ? ? ? cluster_columns = column_dend, # 列聚類(lèi)方法指定為前面設(shè)置的dendrogram對(duì)象
? ? ? ? column_title = "(A) A heatmap with column annotations", # 標(biāo)題
? ? ? ? show_column_names = FALSE, # 不顯示列名
? ? ? ? column_split = 3,? # 列分割數(shù)
? ? ? ? row_dend_width = unit(2, "cm"), # 行聚類(lèi)樹(shù)的寬度
? ? ? ? row_split = rep(c("A", "B"), 9), # 行分割后的命名
? ? ? ? row_km = 2, # 行k-means聚類(lèi)的類(lèi)別數(shù)
? ? ? ? row_order = 1:18
? ? ? ? )
如果設(shè)置了row_order或column_order浅侨,在每一行/列分割切片中,它仍然是有序的证膨。
還可以對(duì)于聚類(lèi)樹(shù)顯示的順序進(jìn)行控制如输。當(dāng)row_split/column_split或row_km/column_km設(shè)置為分類(lèi)變量(向量或數(shù)據(jù)框)時(shí),默認(rèn)情況下,會(huì)對(duì)切片的均值應(yīng)用額外的聚類(lèi)以顯示切片級(jí)別的層次結(jié)構(gòu)不见。在這種情況下澳化,您無(wú)法精確控制切片的順序,因?yàn)樗怯汕衅木垲?lèi)控制的稳吮。
不過(guò)缎谷,你可以設(shè)置cluster_row_slices或cluster_column_slices為 FALSE進(jìn)而關(guān)閉聚類(lèi)上切片,現(xiàn)在你可以精確地控制切片的順序灶似。
當(dāng)沒(méi)有切片聚類(lèi)時(shí)列林,每個(gè)切片的順序可以由levels中row_split/column_split 的每個(gè)變量的控制(在這種情況下,每個(gè)變量都應(yīng)該是一個(gè)因子)喻奥。如果所有變量都是字符席纽,則默認(rèn)順序?yàn)閡nique(row_split)orunique(column_split) 捏悬。
比如下面的結(jié)果:
Heatmap(mat, name = "mat",
? row_split = factor(rep(LETTERS[1:3], 6), levels = LETTERS[3:1]),
? ? column_split = factor(rep(letters[1:6], 4), levels = letters[6:1]),
? ? cluster_row_slices = FALSE,
? ? cluster_column_slices = FALSE)
我們通過(guò)設(shè)置cluster_row_slices或cluster_column_slices為 FALSE進(jìn)而關(guān)閉聚類(lèi)上切片撞蚕。所以就嚴(yán)格按照我們?cè)O(shè)置的因子順序來(lái)顯示了。但是由于高一層級(jí)的聚類(lèi)樹(shù)打亂了过牙,所以就沒(méi)有辦法顯示了甥厦。
Heatmap(mat, name = "mat",
? row_split = factor(rep(LETTERS[1:3], 6), levels = LETTERS[3:1]),
? ? column_split = factor(rep(letters[1:6], 4), levels = letters[6:1]),
? ? cluster_row_slices = FALSE,
? ? cluster_column_slices = FALSE,
? ? row_title_rot = 0)
#行標(biāo)題默認(rèn)旋轉(zhuǎn),您可以設(shè)置row_title_rot = 0為水平寇钉,這個(gè)類(lèi)似于gggplot里面對(duì)于文字角度的控制刀疙。
還可以通過(guò)row_title,column_title指定標(biāo)題扫倡。當(dāng)指定為單個(gè)字符串長(zhǎng)度谦秧,則它就像所有切片的單個(gè)標(biāo)題。當(dāng)指定向量的時(shí)候撵溃,則是每個(gè)切片一個(gè)標(biāo)題疚鲤。
Heatmap(mat, name = "mat",
? row_split = factor(rep(LETTERS[1:3], 6), levels = LETTERS[3:1]),
? ? column_split = factor(rep(letters[1:6], 4), levels = letters[6:1]),
? ? cluster_row_slices = FALSE,
? ? cluster_column_slices = FALSE,
? ? row_title_rot = 0,
? ? #row_title = "(A) A heatmap with column annotations",
? ? row_title = c("t1","t2","t3")
)
在行/列上應(yīng)用拆分時(shí),可以將行/列標(biāo)題和行/列名稱(chēng)的圖形參數(shù)指定為與切片數(shù)相同的長(zhǎng)度缘挑。
比如row_title_gp 和column_title_gp用來(lái)修改title的一些參數(shù)集歇。row_names_gp 和column_names_gp用來(lái)修改names的一些圖形參數(shù)。
Heatmap(mat, name = "mat",
? ? row_km = 2, row_title_gp = gpar(col = c("red", "blue"), font = 1:2),
? ? row_names_gp = gpar(col = c("green", "orange"), fontsize = c(10, 14)),
? ? column_km = 3, column_title_gp = gpar(fill = c("red", "blue", "green"), font = 1:3),
? ? column_names_gp = gpar(col = c("green", "orange", "purple"), fontsize = c(10, 14, 8)))
行/列切片之間的間隙空間可以通過(guò)row_gap/ column_gap控制语淘。該值可以是單個(gè)單位或單位向量诲宇。
可以設(shè)置一致的縫隙:row_gap=unit(5,"mm"),也可以分別設(shè)置惶翻,例如:row_gap=unit(c(2,4),"mm")
Heatmap(mat, name = "mat",
? ? row_km = 2, row_title_gp = gpar(col = c("red", "blue"), font = 1:2),
? ? row_names_gp = gpar(col = c("green", "orange"), fontsize = c(10, 14)),
? ? column_km = 3, column_title_gp = gpar(fill = c("red", "blue", "green"), font = 1:3),
? ? column_names_gp = gpar(col = c("green", "orange", "purple"), fontsize = c(10, 14, 8)),
? ? row_gap = unit(5, "mm")
)
通過(guò)border=TRUE來(lái)設(shè)置邊框姑蓝。
這次是complexheatmap基本熱圖的一些畫(huà)法,下面的帖子我們學(xué)習(xí)如果添加各種annotation吕粗。
通過(guò)設(shè)置添加熱圖邊框時(shí)它掂,會(huì)添加border = TRUE每個(gè)切片的邊框。
通過(guò)設(shè)置添加熱圖邊框時(shí),會(huì)添加border = TRUE每個(gè)切片的邊框虐秋。