筆記內(nèi)容:
- 熱圖的應(yīng)用意義
- 包的安裝
- scale的作用
- 作圖細節(jié):系統(tǒng)發(fā)生樹,label, color key的問題等
- 補充:添加多行ColSideColors
- 補充:heatmap.3示例
- 補充:ComplexHeatmap::Heatmap
熱圖的應(yīng)用意義
在paper中常常能看到熱圖(heatmap):“形式為功能服務(wù)”。在我們常見的,使用矩陣作為Input的二維熱圖中,多為基因表達差異,16s分析中不同分組的物種豐度/相對豐度差異提供線索及可視化效果。
使用熱圖可以直觀通過顏色的深淺和差異判斷樣本/組別之間的差異。結(jié)合統(tǒng)計檢驗的顯著性結(jié)果,可以評估出顯著性的方向。熱圖可以通過算法生成系統(tǒng)樹,表現(xiàn)各個subject及feature的聚類關(guān)系。
在R中可以使用gplots包中的heatmap.2輕松畫出熱圖。但對于其scale, 系統(tǒng)樹的建立,以及很細節(jié)的字體大小,圖片大小,color key的數(shù)值范圍設(shè)置,對應(yīng)的顏色設(shè)置等,均需要通過參數(shù)的調(diào)整實現(xiàn)。雖然比起其他編程工具,R是個封裝很嚴實的軟件,這意味著許多參數(shù)不能很靈活的去修改。但這不妨礙我們充分使用它帶來的便利。
包的安裝
install.packages("gplots")
install.packages("RColorBrewer")
install.packages("devtools")
library(devtools)
install.github("stanstrup/massageR")
安裝massageR包是為了對熱圖的input矩陣做一些處理,這個包的安裝有些曲折,在win10系統(tǒng)上按照以下兩步先安裝devtools再通過github裝massageR沒問題,但是在linux系統(tǒng)上不能在R sutdio里直接這么安裝,詳見 R使用筆記第11條
在本筆記中不使用massageR包也可以,heatmap.2可以搞定。
scale的作用
plot_color = c('orange','green')[treatment]
# treatment為meta data中提取出的分組信息,必須為一個factor
# 如果在input data中把sampleID整理為分組的順序,那么會在colsidecolors這里顯示為整齊的分為兩組。
heatmap.2(x, #Input必須是matrix
trace="none", # trace可以給每個色塊中添加一條線,與行平行或者與列平行。其與色塊中心的距離代表了這個值被顯示的比例。
scale="none", # scale在這里
ColSideColors = plot_color, # 按照treatment組別給每個subject一個顏色
dendrogram = "row", # 生成row的系統(tǒng)發(fā)生樹
symbreaks = TRUE,
col=rev(colorRampPalette(brewer.pal(10, "RdBu"))(20)), # color key, 后面詳敘
breaks = seq(-0.5,0.5,0.05), # 還是color key
density.info=c("none"), # 還是color key
margins=c(8,16), # 調(diào)整熱圖大小比例
cexRow = 0.8, cexCol = 1.0, # 行列名字體大小
srtCol = 45, offsetCol = -0.5 # 調(diào)整列名的字體傾斜45度,距離熱圖的距離縮小。
)

會出現(xiàn)這樣的圖。很丑,看不出規(guī)律。這是因為我們input的矩陣還沒有經(jīng)過標準化(normalized/scaling)。許多值集中在一個很小的范圍,突然出現(xiàn)幾個很大的值,大得不成比例。導(dǎo)致這種情況:為了照顧那幾個極端值,大部分值之間的差異被掩蓋掉了,所以留下大片幾乎一樣的顏色。標準化即經(jīng)過一定比例控制,將數(shù)據(jù)的規(guī)律保留,并將數(shù)值標化在一個相對穩(wěn)定的范圍內(nèi),更加便于作圖。
但是如果把scale的參數(shù)調(diào)整為scale="row"
scale = "row" 即針對行進行標化,

作圖細節(jié):系統(tǒng)發(fā)生樹,label,color key的問題等
heatmap.2(x,
trace="none",
scale="none", # scale在這里
ColSideColors = plot_color, # 按照treatment組別給每個subject一個顏色
Rowv = TRUE, # 決定是否要將row按照系統(tǒng)發(fā)生樹cluster的結(jié)果重新排序,注意要和dendrogram一致。同理還有Colv =
dendrogram = "row", # 生成row的系統(tǒng)發(fā)生樹
symbreaks = TRUE,
col=rev(colorRampPalette(brewer.pal(10, "RdBu"))(20)),
# color key在左上角,本圖中為row-scale過,所以為row Z-score
# 設(shè)置color key的顏色,這里為20個色塊構(gòu)成,從藍色到紅色
breaks = seq(-0.5,0.5,0.05),
# 設(shè)置color key的范圍,這里必須和上面col = 的20個色塊對應(yīng)起來。
# 從-0.5到0.5,以0.05為一個step,一共20個step, 對應(yīng)20個色塊。
density.info=c("none"),
# 設(shè)置color key中是否需要顯示各個范圍的count數(shù)目及其比例。none就不設(shè)置。
margins=c(8,16),
# 調(diào)整熱圖大小比例,在label的名字特別長的時候可以嘗試調(diào)整,讓Label顯示完全
cexRow = 0.8, cexCol = 0.8, # 行/列名字體大小
keysize = 0.8 # 可以配合margins = 調(diào)節(jié)圖例的大小及整個圖的比例
colsep = c(15, 54)
#在熱圖中加入白色豎線,從而將其分成不同的部分。這個表示在第15個及第54個column的位置加上豎線。同理還有rowsep =
)
如果想把生成系統(tǒng)發(fā)生樹聚類后的數(shù)據(jù)拿出來(即獲得聚類后重新排列后的數(shù)據(jù)):
map <- heatmap.2(as.matrix(x), ...)
x_reorder <- x[rev(map$rowInd), map$colInd]
# x_reorder 為重新排序后的數(shù)據(jù)
heatmap.2的文件非常詳細,見這個鏈接
添加多行ColSideColors
需要用到heatmap.plus包,其各種參數(shù)和heatmap.2差不多,但是heatmap.2只能為ColSideColors設(shè)置與column長度相當?shù)腸haracter, heatmap.plus可以設(shè)置為matrix: 其實只用把兩個(或者多個)含有顏色分配信息的vectorcbind到一起就可以了。
調(diào)整參數(shù)為ColSideColors = color # 注意使用heatmap.plus


另外有個升級版heatmap.3,參數(shù)基于heatmap.2,同樣可以添加多行ColSideColors:
#通過devtools把heatmap.3的代碼導(dǎo)入本地:
library(devtools)
source_url("https://raw.githubusercontent.com/obigriffith/biostar-tutorials/master/Heatmaps/heatmap.3.R")
heatmap.3(...)
### 2019.7.9 notes: 這個好像不是GMD包里的heatmap.3...???但是仍然可以用...???
# 以下是GMD包里的heatmap.3,注意和上面的不一樣?。?!
# 安裝:
# (建議最好還是用上面那個heatmap.3,下面那篇帖子很全,GMD沒有多少demo,color也不知道怎么設(shè)置=_=)
packageurl <- "https://cran.r-project.org/src/contrib/Archive/GMD/GMD_0.3.3.tar.gz"
install.packages(packageurl, repos=NULL, type="source")
library(GMD)
heatmap.3(...)
參考這篇BioStars上的帖子
參考heatmap.3的文檔
heatmap.3示例
library(devtools)
source_url("https://raw.githubusercontent.com/obigriffith/biostar-tutorials/master/Heatmaps/heatmap.3.R")
install.packages("mlbench") # 只是用里面的示例數(shù)據(jù)Glass
library(mlbench)
data(Glass)
# Glass如下所示
RI Na Mg Al Si K Ca Ba Fe Type
1 1.52101 13.64 4.49 1.10 71.78 0.06 8.75 0.00 0.00 1
2 1.51761 13.89 3.60 1.36 72.73 0.48 7.83 0.00 0.00 1
3 1.51618 13.53 3.55 1.54 72.99 0.39 7.78 0.00 0.00 1
4 1.51766 13.21 3.69 1.29 72.61 0.57 8.22 0.00 0.00 1
5 1.51742 13.27 3.62 1.24 73.08 0.55 8.07 0.00 0.00 1
Glass$fake_gp = c(rep('g1',107),rep('g2',107)) # 加一個fake_gp的分組
Glass$fake_gp = factor(Glass$fake_gp,levels = c('g1','g2'))
# 注意一定要轉(zhuǎn)成factor
color_matrix = cbind(brewer.pal(7,"Set1")[Glass$Type],
c('black','grey50')[Glass$fake_gp])
colnames(color_matrix) = c('Type','fake_gp')
# 給color_matrix加上colname, 會當作colorbar名稱在圖中顯示
df = Glass[1:9]
heatmap.3(df,
scale="col",
dendrogram = "row",
distfun = function(x){as.dist(1-cor(t(x)))}, # 不設(shè)置的話會用默認的
hclustfun = function(x){hclust(x, method = 'average')}, # 不設(shè)置的話會用默認的
Rowv = TRUE, Colv = FALSE,
symbreaks = FALSE,
col=rev(brewer.pal(10, "RdBu")),
RowSideColors = t(color_matrix), # 注意用t()轉(zhuǎn)換,因為這里是rowside, colside則不用
breaks = seq(-1,1,0.2),
density.info=c("none"),
margins=c(10,10), # 設(shè)置熱圖橫縱兩個方向的留白
cexRow = 1, cexCol = 1,
# colsep = c(24,48,72),
# sepwidth = c(0.2,0.2), # 如果需要熱圖從中間分開,則設(shè)置這兩個參數(shù)
keysize = 0.8,
key = TRUE,
symkey = FALSE
# KeyValueName = ... # 設(shè)置這個參數(shù)則替換“Column Z-Score”文本
)

這個post很有參考價值,包括了
symkey調(diào)整color的用途,不同包默認的建樹設(shè)置等。
ComplexHeatmap::Heatmap
ComplexHeatmap是一個bioconductor的包,需要這樣安裝:參考
BiocManager::install("ComplexHeatmap")
官方的Documentation, 是非常詳細的使用指南:https://jokergoo.github.io/ComplexHeatmap-reference/book/introduction.html
優(yōu)點在于自動附上了圖例;可以添加多個row或者column的annotation;在annotation是連續(xù)型變量是不用手動設(shè)置intervel??梢园裩eatmap.2中構(gòu)建的樹完整移植過來。
一個示例,使用瞎掰的數(shù)據(jù)集mat
library(ComplexHeatmap)
library(circlize)
library(dendextend)
library(RColorBrewer)
# 瞎掰數(shù)據(jù)集mat
set.seed(123)
mat = matrix(rnorm(100),10)
rownames(mat) = paste0("R",1:10)
colnames(mat) = paste0("c",1:10)
# 再掰一個meta data,用于做heatmap的annotation
meta_mat = data.frame(ind=1:10)
meta_mat$m1 = c(rep('a',5),rep('b',5))
meta_mat$m2 = c(rep('c',2),rep('d',3),rep('e',5))
meta_mat$m3 = rnorm(10)
數(shù)據(jù)集一覽:


# 給heatmap的行做annotation, 注意對應(yīng)每個變量,指定顏色
row_ha = rowAnnotation(df=meta_mat[,c('m1','m2','m3')],
col=list(m1=c('a' = 'blue','b'='red'),
m2=c('c'='pink','d'='darkgreen','e'='grey50'),
m3=circlize::colorRamp2(c(-1,0,1), c("blue", "white", "red"))))
ComplexHeatmap::Heatmap(mat,name='mat',
column_title = 'test_mat',
right_annotation = row_ha,
col = rev(brewer.pal(10,"RdBu")), # 熱圖的顏色
column_dend_height = unit(3,"cm"), # 設(shè)置樹的大小
# 這里設(shè)置了一個對聚類樹的分割及上色,在h=2.5處分簇并著色:
cluster_columns = dendextend::color_branches(as.dendrogram(hclust(dist(mat))),
h = 2.5),
show_column_names = F # 不顯示column name
)

如果用heatmap.3來做:
meta_mat$m1 = factor(meta_mat$m1,levels = c('a','b'))
meta_mat$m2 = factor(meta_mat$m2,levels = c('c','d','e'))
# 設(shè)置intervel
meta_mat$inter = findInterval(meta_mat$m3,
sort(meta_mat$m3,decreasing = F))
pal = colorRampPalette(c('white','red'))
color_matrix = data.frame(
m1=c('blue','red')[meta_mat$m1],
m2=c('pink','darkgreen','grey50')[meta_mat$m2],
m3=pal(nrow(meta_mat))[meta_mat$inter]
)
hh = heatmap.3(as.matrix(mat),
dendrogram = 'both',
distfun = function(x){as.dist(1-cor(t(x)))},
hclustfun = function(x){hclust(x,method = 'ward.D2')},
col = rev(brewer.pal(10,'RdBu')),
Rowv = TRUE, Colv = TRUE,
ColSideColors = as.matrix(color_matrix)
)

把heatmap.3中的樹移植到ComplexHeatmap::Heatmap中去:
ComplexHeatmap::Heatmap(mat,name='mat',
column_title = 'test_mat',
right_annotation = row_ha,
col = rev(brewer.pal(10,"RdBu")), # 熱圖的顏色
column_dend_height = unit(3,"cm"), # 設(shè)置樹的大小
# 換成hh的術(shù),并且設(shè)置一個對聚類樹的分割及上色,在h=2.5處分簇并著色:
cluster_columns = dendextend::color_branches(hh$colDendrogram,
h = 2.5),
show_column_names = F # 不顯示column name
)