R可视化之ComplexHeatmap【一】:颜色、标题、聚类

特别声明:本部分(系列)内容均来自顾祖光博士对ComplexHeatmap的介绍,仅为学习交流,尊重原创。

闲话少说,先说顾老师:
顾祖光老师,现在德国癌症中心从事与NGS相关的生物信息学研究,其本科和研究生均在南京大学生命科学学院就读:

  • 2001-09 to 2005-07 | Undergraduate (School of Life Science, Nanjing University)
  • 2005-09 to 2008-07 | Master (School of Life Science, Nanjing University)
  • 2008-09 to 2012-07 | PhD (School of Life Science, Nanjing University)

为什么要介绍顾祖光博士,因为很有可能你所需要的工具(尤其是可视化),很多你都能从他那儿找到答案,看看顾祖光老师有多高产:

R

这还仅仅是他开发的R包,其它还有一系列perl工具。本部分(系列)主要是学习顾老师被引用量最高的一个R包:ComplexHeatmap。顾老师的这个包绘制热图的核心结构如下:

安装

  • 通过 bioconductor 安装:
if (!requireNamespace("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install("ComplexHeatmap")
  • 通过 github 安装最新版
library(devtools)
install_github("jokergoo/ComplexHeatmap")

基础——单个热图绘制

library(ComplexHeatmap)
library(dplyr)
library(tidyverse)
library(circlize)

#生成矩阵
mat = matrix(rnorm(100, mean = 0, sd = 1), nrow = 10)
rownames(mat) = paste('row', seq_len(10), sep = '_')
colnames(mat) = paste('col', seq_len(10), sep = '_')

#绘制基础热图
Heatmap(mat)
  • 指定热图颜色(包括连续型变量、离散型变量、NA值配色以及热图边界配色四部分内容)

热图中的数据一般都是连续型变量,ComplexHeatmap推荐大家使用circlize包中的colorRamp2进行颜色映射设定,函数参数包括断点和断点对应的颜色,这个包也是顾博士的。

col = colorRamp2(breaks = c(-4, 0, 4), colors = c('green', 'white', 'red'))
Heatmap(mat, name = 'mat', col = col)


需要注意的是,这里的颜色映射是不受异常值的影响的,也就是说上面的例子中,如果有一个异常值大于4,那么它的颜色会被自动标注成为红色

这个颜色还有另外的妙用,我们常常想比较不同热图中的值的大小,但是又担心不同热图的颜色与数值大小的映射标准不一,ComplexHeatmap为我们提供了解决方案:只要几个热图共用一个相同的配色方案,那么它们之间就是可比的

当然你也可以通过直接输入含有一系列颜色的向量来对热图进行颜色指定,不过需要注意:你所指定的颜色ComplexHeatmap是默认将其映射到整个数据矩阵的数据范围内,这意味着异常值会影响到整个热图的颜色配置。举例来说,这两种配色是一样的:

col = rainbow(3)
col = colorRamp2(breaks = seq(min(mat), max(mat), length = 3), colors = rainbow(3))

如果热图中的数据是离散型变量,比如是不同的字符,我们应该如何绘制呢?

#离散型变量
#生成矩阵
mat = matrix(sample(letters[1:4], 100, replace = T), ncol = 10)
#指定颜色(structure()函数)
col = structure(rainbow(4), names = letters[1:4])
#绘制热图
Heatmap(mat, name = 'mat', col = col)


在这里用到了一个structure()函数,,不会也没关系,这个函数只是构建了一个颜色到元素之间的映射,同样的目标还可以用下面的代码实现,而且更容易理解,大家以后可以用起来:

col = rainbow(4)
names(col) <- letters[1:4]

那么我们如何处理NA值的配色?(在热图的绘制当中是允许存在NA值的)

#NA值配色
#生成矩阵
index = sample(c(TRUE, FALSE), 100, replace = T, prob = c(1, 9))
mat[index] = NA
#绘制热图
Heatmap(mat, name = 'mat', col = c('blue', 'white', 'red'))


图中的NA值,统一使用了灰色进行标识,如果我们想自定义这个颜色,可以通过添加na_col参数来实现:

Heatmap(mat, name = 'mat', col = c('blue', 'white', 'red'), na_col = 'black')


最后一个问题,我们如何来自定义热图的边界呢?
这个问题分为两个层次,一个是热图中每个小方块,一个是整个热图边界。首先介绍如何控制热图中每个小方块的颜色,主要是使用rect_gp

mat = matrix(sample(letters[1:4], 100, replace = T), ncol = 10)
col = rainbow(4)
names(col) <- letters[1:4]
Heatmap(matrix = mat, col = col, rect_gp = gpar(col = 'white', lwd = 2))


可以看到,小方块的边界已经变成白色了。
如何控制整个热图的边界呢?主要是使用border/border_gp

Heatmap(matrix = mat, col = col, border_gp = gpar(col = 'black', lty = 2))


整个热图的边界已经有了黑色(col = 'black')的虚线(lty = 2)。

  • 自定义标题(这部分主要包括如何给热图的行和列添加标题)

这部分内容概括为以下代码框架:

Heatmap(matrix, #绘图矩阵 [matrix]
        col, #矩阵配色 [vector]
        name, #矩阵图例标题 [character]
        column_title, #矩阵列标题 [character]
        column_title_gp, #指定矩阵列标题相关属性 
        column_title_side, #指定矩阵列标题位置(顶部和底部)[character; 'top' or 'bottom']
        column_title_rot #指定列标题旋转角度,仅支持水平和竖直两种呈现形式 [numeric]
        )

其余参数没什么好讲的,主要介绍一下 column_title_gp 参数。这个参数主要是通过gpar函数指定标题的性质。

column_title_gp = gpar(fontsize = 20,  #指定字体大小
                       fontface = "bold",  #指定字体风格
                       fill = "red",  #指定标题背景填充色
                       col = "white",  #指定字体颜色
                       border = "blue" #指定标题背景框边框色
                       )

例如:

mat = matrix(rnorm(100, mean = 0, sd = 1), nrow = 10)
Heatmap(matrix = mat,
        col = col,
        name = 'mat',
        column_title = 'The heatmap for mat',
        column_title_side = 'top', 
        column_title_rot = 0,
        column_title_gp = gpar(fontsize = 20,
                               fontface = 'bold', 
                               fill = 'red',
                               col = 'white',
                               border = 'blue'))
  • 聚类

默认情况下,绘制热图时会对行和列进行聚类,我们可以通过cluster_rowscluster_cols关闭聚类功能:

mat = matrix(rnorm(100, mean = 0, sd = 1), nrow = 10)
rownames(mat) = paste('row', seq_len(10), sep = '_')
colnames(mat) = paste('col', seq_len(10), sep = '_')
Heatmap(matrix = mat, cluster_rows = F, name = 'mat')


有的时候我们觉得聚类时左右两边的树状结构影响图的观感,这时候我们可以通过show_row_dendshow_col_dend来进行隐藏:

Heatmap(matrix = mat, show_row_dend = F, name = 'mat')

当然有的时候,树是很重要的,你可能不能进行隐藏,但是你可以把树的size变小:

Heatmap(mat, name = "mat", 
        column_dend_height = unit(5, "mm"), 
        row_dend_width = unit(5, "mm"))

如你所想,聚类的树状结构你可以放在任何位置,这是通过row_dend_sidecol_dend_side实现的:

Heatmap(matrix = mat, row_dend_side = 'right', name = 'mat')

本期到此为止,下期内容:行(列)顺序、行(列)名。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 225,337评论 6 524
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,560评论 3 406
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,632评论 0 370
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 61,219评论 1 303
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,219评论 6 401
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,670评论 1 316
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,018评论 3 431
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 41,000评论 0 280
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,552评论 1 326
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,565评论 3 347
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,692评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,280评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,009评论 3 341
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,435评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,587评论 1 277
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,276评论 3 383
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,752评论 2 367

推荐阅读更多精彩内容