R使用笔记: heatmap.2绘制热图

笔记内容:

  • 热图的应用意义
  • 包的安装
  • scale的作用
  • 作图细节:系统发生树,label, color key的问题等
  • 补充:添加多行ColSideColors
  • 补充:heatmap.3示例
  • 补充:ComplexHeatmap::Heatmap

热图的应用意义

在paper中常常能看到热图(heatmap):“形式为功能服务”。在我们常见的,使用矩阵作为Input的二维热图中,多为基因表达差异,16s分析中不同分组的物种丰度/相对丰度差异提供线索及可视化效果。

使用热图可以直观通过颜色的深浅和差异判断样本/组别之间的差异。结合统计检验的显著性结果,可以评估出显著性的方向。热图可以通过算法生成系统树,表现各个subject及feature的聚类关系。

在R中可以使用gplots包中的heatmap.2轻松画出热图。但对于其scale, 系统树的建立,以及很细节的字体大小,图片大小,color key的数值范围设置,对应的颜色设置等,均需要通过参数的调整实现。虽然比起其他编程工具,R是个封装很严实的软件,这意味着许多参数不能很灵活的去修改。但这不妨碍我们充分使用它带来的便利。

包的安装
install.packages("gplots")
install.packages("RColorBrewer")

install.packages("devtools")
library(devtools)
install.github("stanstrup/massageR")

安装massageR包是为了对热图的input矩阵做一些处理,这个包的安装有些曲折,在win10系统上按照以下两步先安装devtools再通过github装massageR没问题,但是在linux系统上不能在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的系统发生树
          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),  # 调整热图大小比例
          cexRow = 0.8, cexCol = 1.0,   # 行列名字体大小
          srtCol = 45, offsetCol = -0.5 # 调整列名的字体倾斜45度,距离热图的距离缩小。
)

会出现这样的图。很丑,看不出规律。这是因为我们input的矩阵还没有经过标准化(normalized/scaling)。许多值集中在一个很小的范围,突然出现几个很大的值,大得不成比例。导致这种情况:为了照顾那几个极端值,大部分值之间的差异被掩盖掉了,所以留下大片几乎一样的颜色。标准化即经过一定比例控制,将数据的规律保留,并将数值标化在一个相对稳定的范围内,更加便于作图。

但是如果把scale的参数调整为scale="row"
scale = "row" 即针对行进行标化,

作图细节:系统发生树,label,color key的问题等
heatmap.2(x,            
          trace="none",
          scale="none",    # scale在这里
          ColSideColors = plot_color,   # 按照treatment组别给每个subject一个颜色

          Rowv = TRUE,   # 决定是否要将row按照系统发生树cluster的结果重新排序,注意要和dendrogram一致。同理还有Colv =  
          dendrogram = "row",   # 生成row的系统发生树
          symbreaks = TRUE,
          col=rev(colorRampPalette(brewer.pal(10, "RdBu"))(20)),  
          # color key在左上角,本图中为row-scale过,所以为row Z-score
          # 设置color key的颜色,这里为20个色块构成,从蓝色到红色

          breaks = seq(-0.5,0.5,0.05),   
          # 设置color key的范围,这里必须和上面col = 的20个色块对应起来。
          # 从-0.5到0.5,以0.05为一个step,一共20个step, 对应20个色块。
          
          density.info=c("none"),  
          # 设置color key中是否需要显示各个范围的count数目及其比例。none就不设置。
          
          margins=c(8,16),  
          # 调整热图大小比例,在label的名字特别长的时候可以尝试调整,让Label显示完全
          cexRow = 0.8, cexCol = 0.8,   # 行/列名字体大小
          keysize = 0.8  # 可以配合margins = 调节图例的大小及整个图的比例
         
          colsep = c(15, 54) 
          #在热图中加入白色竖线,从而将其分成不同的部分。这个表示在第15个及第54个column的位置加上竖线。同理还有rowsep = 
)

如果想把生成系统发生树聚类后的数据拿出来(即获得聚类后重新排列后的数据):

map <- heatmap.2(as.matrix(x), ...)
x_reorder <- x[rev(map$rowInd), map$colInd]
# x_reorder 为重新排序后的数据

heatmap.2的文件非常详细,见这个链接

添加多行ColSideColors

需要用到heatmap.plus包,其各种参数和heatmap.2差不多,但是heatmap.2只能为ColSideColors设置与column长度相当的character, heatmap.plus可以设置为matrix: 其实只用把两个(或者多个)含有颜色分配信息的vectorcbind到一起就可以了。
调整参数为ColSideColors = color # 注意使用heatmap.plus

另外有个升级版heatmap.3,参数基于heatmap.2,同样可以添加多行ColSideColors:

#通过devtools把heatmap.3的代码导入本地:
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也不知道怎么设置=_=)
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")  # 只是用里面的示例数据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'))
# 注意一定要转成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)))},  # 不设置的话会用默认的
          hclustfun = function(x){hclust(x, method = 'average')},  # 不设置的话会用默认的
          Rowv = TRUE, Colv = FALSE,
          symbreaks = FALSE,
          col=rev(brewer.pal(10, "RdBu")),
          RowSideColors = t(color_matrix),  # 注意用t()转换,因为这里是rowside, colside则不用
          breaks = seq(-1,1,0.2),
          density.info=c("none"),
          margins=c(10,10),  # 设置热图横纵两个方向的留白
          cexRow = 1, cexCol = 1,
          # colsep = c(24,48,72),
          # sepwidth = c(0.2,0.2),  # 如果需要热图从中间分开,则设置这两个参数
          keysize = 0.8,
          key = TRUE,
          symkey = FALSE
          # KeyValueName = ...  # 设置这个参数则替换“Column Z-Score”文本
)


这个post很有参考价值,包括了symkey调整color的用途,不同包默认的建树设置等。

ComplexHeatmap::Heatmap

ComplexHeatmap是一个bioconductor的包,需要这样安装:参考
BiocManager::install("ComplexHeatmap")

官方的Documentation, 是非常详细的使用指南:https://jokergoo.github.io/ComplexHeatmap-reference/book/introduction.html

优点在于自动附上了图例;可以添加多个row或者column的annotation;在annotation是连续型变量是不用手动设置intervel。可以把heatmap.2中构建的树完整移植过来。

一个示例,使用瞎掰的数据集mat

library(ComplexHeatmap)
library(circlize)
library(dendextend)
library(RColorBrewer)

# 瞎掰数据集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)

数据集一览:

mat
meta_mat
# 给heatmap的行做annotation, 注意对应每个变量,指定颜色
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"),  # 设置树的大小
                        # 这里设置了一个对聚类树的分割及上色,在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'))
# 设置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"),  # 设置树的大小
                        # 换成hh的术,并且设置一个对聚类树的分割及上色,在h=2.5处分簇并着色: 
                        cluster_columns = dendextend::color_branches(hh$colDendrogram,
                                                                     h = 2.5),
                        show_column_names = F  # 不显示column name
                        )
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容