你要的 ComplexHeatmap TA 来了!
点击上方「蓝字」关注我们
介绍
ComplexHeatmap
包是一个非常强大的 绘制热图 的 利器 !他的设计灵感来自于 pheatmap
这个包,作者是 顾祖光博士 ,当然 circlize
包也是这位大佬开发的,他的介绍我在写介绍 circlize 包时介绍过。
作者顾祖光南京大学博士毕业,现在在德国癌症研究中心工作,是一名生信研究员,研究领域有基因组学、表观组学、开发软件、可视化等等。其中 ComlexHeatmap、EnrichedHeatmap、simplifyEnrichment 等强大的 R 包都是他开发的,大佬!
安装方式:
BiocManager::install("ComplexHeatmap")
# 安装最新版
library(devtools)
install_github("jokergoo/ComplexHeatmap")
总体设计:
单个热图由 热图主体 和 热图组件 组成。热图主体可以 按行和列分割 。热图组件包括标题
、树状图
、矩阵名称
和热图注释
,它们被放置在主体的四面。
热图列表 由一系列的热图和注释组成,标题和注释围绕在热图四周。对于热图列表来说,一个重要的点是所有热图和注释的 行/列
都要进行调整,以便所有热图和注释中的同一 行/列
对应于相同的特征。
此外热图列表也可以按行和列进行分割。
作品展示:
ComplexHeatmap 包是以面向对象的方式实现的。要描述一个热图列表,有以下类:
Heatmap
类:包含热图主体、行/列名称、标题、树状图和行/列注释的单个热图。HeatmapList
类:热图列表和热图注释列表。HeatmapAnnotation
类:定义行注释和列注释的列表。热图注释可以是热图的组件,也可以是独立的。
其它的内部类:
SingleAnnotation
类:定义单个行注释或列注释。HeatmapAnnotation 对象包含一个 SingleAnnotation 对象列表。ColorMapping
类:从值到颜色的映射。主矩阵的颜色映射和注释由 ColorMapping 类控制。AnnotationFunction
类:构建自定义的注释。这是创建用户定义的注释图形的基础。
内容概要
内容太多,我会选择性的选择关于 热图
的主要部分介绍。
1、A Single Heatmap 2、Heatmap Annotations 3、A List of Heatmaps 4、Legends 5、Heatmap Decoration 6、OncoPrint 7、UpSet plot 8、Other High-level Plots 9、Integrate with other packages 10、Interactive heatmap 11、More Examples
A Single Heatmap
构造矩阵数据:
set.seed(123)
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)] # random shuffle rows and columns
rownames(mat) = paste0("row", seq_len(nr))
colnames(mat) = paste0("column", seq_len(nc))
# 查看内容
head(mat,3)
column1 column2 column3 column4 column5 column6 column7 column8
row1 0.9047416 -0.35229823 0.5016096 1.26769942 0.8251229 0.1621522 -0.2869867 0.6803262
row2 0.9088297 0.79157121 1.0726316 0.01299521 0.1391978 0.4683369 1.2814948 0.3899826
row3 0.2807467 0.02987497 0.7052595 1.21514235 0.1747267 0.2094912 -0.6423579 -0.3139530
column9 column10 column11 column12 column13 column14 column15 column16
row1 -0.1629658 0.8254537 0.7821773 -0.4962536 -0.0895258 -0.3552033 0.1072694 0.9632220
row2 -0.3473535 1.3508922 1.1183375 2.0500545 1.3770269 -0.7743764 0.9829664 0.2385438
row3 0.2175907 -0.2973086 0.4322058 -0.2580319 -0.5686518 -0.5132105 -0.0451598 0.8227288
column17 column18 column19 column20 column21 column22 column23 column24
row1 -0.39245223 -0.1878014 1.0873632 0.7132199 -0.1853300 -0.1423865 0.6407669 1.3266288
row2 -0.53589561 1.3003544 0.1423789 0.4471643 0.4475628 -0.3125196 0.7057150 0.8120937
row3 -0.02251386 0.2427300 1.0951152 0.5852612 0.1926402 0.5127857 1.6361334 1.1339175
默认绘制热图:
Heatmap(mat)
1、颜色
使用 circlize
包的 colorRamp2 函数生成颜色:
library(circlize)
col_fun = colorRamp2(c(-2, 0, 2), c("green", "white", "red"))
col_fun(seq(-3, 3))
## [1] "#00FF00FF" "#00FF00FF" "#B1FF9AFF" "#FFFFFFFF" "#FF9E81FF" "#FF0000FF"
## [7] "#FF0000FF"
Heatmap(mat, name = "mat", col = col_fun)
颜色映射函数精确地将负值映射为绿色,将正值映射为红色,即使负值和正值的分布不是以零为中心。此外,这种颜色映射功能不受异常值的影响。在下面的图中,聚类严重受离群值的影响(见树形图),但不受颜色映射的影响:
mat2 = mat
mat2[1, 1] = 100000
Heatmap(mat2, name = "mat", col = col_fun,
column_title = "a matrix with outliers")
colorRamp2()使多个热图中的颜色具有 可比性 ,如果它们使用 相同的颜色映射函数设置
。在下面的三个热图中,相同的颜色总是对应着相同的值:
Heatmap(mat, name = "mat", col = col_fun, column_title = "mat")
Heatmap(mat/4, name = "mat", col = col_fun, column_title = "mat/4")
Heatmap(abs(mat), name = "mat", col = col_fun, column_title = "abs(mat)")
如果矩阵是连续的,你也可以简单地提供一个颜色向量,颜色将被线性插值。但是,这种方法对异常值并不有效,因为映射从矩阵中的 最小值 开始,以 最大值 结束。下面的颜色映射设置与colorRamp2(seq(min(mat), max(mat), length = 10), rev(rainbow(10)))
相同:
Heatmap(mat, name = "mat", col = rev(rainbow(10)),
column_title = "set a color vector for a continuous matrix")
如果矩阵包含离散值(数字或字符),则颜色应指定为命名向量,以使离散值与颜色之间的可以映射。如果颜色没有名称,颜色的顺序对应于 unique(mat) 的顺序。注意,现在图例是由颜色映射向量生成的:
discrete_mat = matrix(sample(1:4, 100, replace = TRUE), 10, 10)
head(discrete_mat,3)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 4 1 2 2 2 4 1 2 3 2
## [2,] 4 3 4 1 2 4 3 1 3 3
## [3,] 1 4 3 2 3 1 4 3 2 1
colors = structure(1:4, names = c("1", "2", "3", "4")) # black, red, green, blue
colors
## 1 2 3 4
## 1 2 3 4
Heatmap(discrete_mat, name = "mat", col = colors,
column_title = "a discrete numeric matrix")
或者字符矩阵:
discrete_mat = matrix(sample(letters[1:4], 100, replace = TRUE), 10, 10)
head(discrete_mat,3)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] "b" "b" "b" "b" "b" "b" "a" "d" "c" "b"
## [2,] "a" "b" "b" "d" "a" "b" "b" "c" "b" "d"
## [3,] "c" "b" "a" "d" "b" "b" "d" "c" "b" "a"
colors = structure(1:4, names = letters[1:4])
## a b c d
## 1 2 3 4
Heatmap(discrete_mat, name = "mat", col = colors,
column_title = "a discrete character matrix")
NA 在矩阵中是允许的。你可以通过 na_col
参数控制 NA 的颜色(默认情况下,NA 为 灰色 )。一个包含 NA 的矩阵可以被 Heatmap()聚类,只要在任何行或列之间没有 NA 距离。通常这些情况对应的是稀疏矩阵(填充了大量的 NA 值),表明未知值需要先通过其他方法进行预测。
NA 值不会显示在图例中:
mat_with_na = mat
na_index = sample(c(TRUE, FALSE), nrow(mat)*ncol(mat), replace = TRUE, prob = c(1, 9))
mat_with_na[na_index] = NA
head(mat_with_na[1:3,1:5],3)
## column1 column2 column3 column4 column5
## row1 0.9047416 -0.35229823 NA 1.267699 0.8251229
## row2 0.9088297 0.79157121 1.0726316 NA 0.1391978
## row3 0.2807467 0.02987497 0.7052595 1.215142 0.1747267
Heatmap(mat_with_na, name = "mat", na_col = "black",
column_title = "a matrix with NA values")
颜色空间对于插值颜色很重要。默认情况下,颜色在 LAB color space
中是线性插值的,但您可以在 colorRamp2()
函数中选择颜色空间:
f1 = colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"))
f2 = colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"), space = "RGB")
Heatmap(mat, name = "mat1", col = f1, column_title = "LAB color space")
Heatmap(mat, name = "mat2", col = f2, column_title = "RGB color space")
颜色在不同的颜色空间的变化:
使用 border_gp
参数结合 grid::gpar()
函数控制热图主体边框:
Heatmap(mat, name = "mat", border_gp = gpar(col = "black", lty = 2),
column_title = "set heatmap borders")
使用 rect_gp
参数结合 grid::gpar()
函数控制热图单元格边框:
Heatmap(mat, name = "mat", rect_gp = gpar(col = "white", lwd = 2),
column_title = "set cell borders")
如果 col 颜色参数没有设置,则会使用默认颜色 ComplexHeatmap:::default_col()
,如果是字符矩阵,则使用 circlize::rand_color()
。
rect_gp 允许使用非标准参数类型。如果将其设置为 “none” ,则仍会聚类,但不会在热图主体上绘制任何内容。热图主体上的自定义图形可以通过自定义的 cell_fun
或 layer_fun
添加:
Heatmap(mat, name = "mat", rect_gp = gpar(type = "none"),
column_title = "nothing is drawn in the heatmap body")
2、标题
图形参数可以分别由 row_title_gp
和column_title_gp
设置。记住,应该使用 gpar 来指定图形参数:
Heatmap(mat, name = "mat", column_title = "I am a column title",
row_title = "I am a row title")
column_title_side
参数放置于底部:
Heatmap(mat, name = "mat", column_title = "I am a column title at the bottom",
column_title_side = "bottom")
column_title_gp
设置样式:
Heatmap(mat, name = "mat", column_title = "I am a big column title",
column_title_gp = gpar(fontsize = 20, fontface = "bold"))
标题的旋转可以通过 row_title_rot
和 column_title_rot
设置,但只允许 水平 和 垂直 旋转:
Heatmap(mat, name = "mat", row_title = "row title", row_title_rot = 0)
使用 fill
、col
、boder
参数控制标题样式:
Heatmap(mat, name = "mat", column_title = "I am a column title",
column_title_gp = gpar(fill = "red", col = "white", border = "blue"))
ht_opt$TITLE_PADDING
控制标题与边框顶部距离:
ht_opt$TITLE_PADDING = unit(c(8.5, 8.5), "points")
Heatmap(mat, name = "mat", column_title = "I am a column title",
column_title_gp = gpar(fill = "red", col = "white", border = "blue"))
# 重置
ht_opt(RESET = TRUE)
使用表达式或公式:
Heatmap(mat, name = "mat",
column_title = expression(hat(beta) == (X^t * X)^{-1} * X^t * y))
3、聚类
关闭横向聚类:
Heatmap(mat, name = "mat", cluster_rows = FALSE) # turn off row clustering
关闭列聚类:
Heatmap(mat, name = "mat", show_column_dend = FALSE) # hide column dendrogram
改变聚类树的位置:
Heatmap(mat, name = "mat", row_dend_side = "right", column_dend_side = "bottom")
调整聚类树高度:
Heatmap(mat, name = "mat", column_dend_height = unit(4, "cm"),
row_dend_width = unit(4, "cm"))
计算距离方法
层次聚类分两步执行:计算距离矩阵和聚类。可以通过三种方式为聚类指定距离矩阵:
1、将距离指定为预定义选项:有效值是 dist() 函数和 pearson、 spearman 和 kendall 中支持的方法。相关距离定义为 1 - cor(x, y, method)
。所有这些内置距离方法都允许含有 NA 值。2、自定义函数:用于计算到矩阵的距离。函数应该只包含一个参数。请注意在列上聚类,矩阵将自动转置。 3、一个自定义的函数:用来计算两个向量之间的距离。函数应该只包含两个参数。注意,这可能很慢,因为它是由两个嵌套的 for 循环实现的。
指定距离方法:
Heatmap(mat, name = "mat", clustering_distance_rows = "pearson",
column_title = "pre-defined distance method (1 - pearson)")
使用函数计算聚类:
Heatmap(mat, name = "mat", clustering_distance_rows = function(m) dist(m),
column_title = "a function that calculates distance matrix")
使用自定义函数:
Heatmap(mat, name = "mat", clustering_distance_rows = function(x, y) 1 - cor(x, y),
column_title = "a function that calculates pairwise distance")
对含有异常值的数据使用自定义函数计算距离:
mat_with_outliers = mat
for(i in 1:10) mat_with_outliers[i, i] = 1000
robust_dist = function(x, y) {
qx = quantile(x, c(0.1, 0.9))
qy = quantile(y, c(0.1, 0.9))
l = x > qx[1] & x < qx[2] & y > qy[1] & y < qy[2]
x = x[l]
y = y[l]
sqrt(sum((x - y)^2))
}
比较:
Heatmap(mat_with_outliers, name = "mat",
col = colorRamp2(c(-2, 0, 2), c("green", "white", "red")),
column_title = "dist")
Heatmap(mat_with_outliers, name = "mat",
col = colorRamp2(c(-2, 0, 2), c("green", "white", "red")),
clustering_distance_rows = robust_dist,
clustering_distance_columns = robust_dist,
column_title = "robust_dist")
如果有合适的距离方法(如 stringdist 包中的方法),也可以对字符矩阵进行聚类:
mat_letters = matrix(sample(letters[1:4], 100, replace = TRUE), 10)
# distance in the ASCII table
dist_letters = function(x, y) {
x = strtoi(charToRaw(paste(x, collapse = "")), base = 16)
y = strtoi(charToRaw(paste(y, collapse = "")), base = 16)
sqrt(sum((x - y)^2))
}
Heatmap(mat_letters, name = "letters", col = structure(2:5, names = letters[1:4]),
clustering_distance_rows = dist_letters, clustering_distance_columns = dist_letters,
cell_fun = function(j, i, x, y, w, h, col) { # add text to each grid
grid.text(mat_letters[i, j], x, y)
})
聚类方法
可以通过 clustering_method_rows
和 clustering_method_columns
指定执行层次聚类的方法。可以的方法是 hclust()
函数支持的方法。
Heatmap(mat, name = "mat", clustering_method_rows = "single")
如果你已经有一个聚类对象或一个直接返回一个聚类对象的函数,你可以忽略距离设置并将 cluster_rows 或 cluster_columns 设置为聚类对象或聚类函数。如果它是一个聚类函数,唯一的参数应该是矩阵,它应该返回一个 hclust 或 dendrogram 对象或一个可以转换为 dendrogram 类的对象。
在以下示例中,我们通过预先计算的聚类对象或聚类函数使用 cluster
包中的方法执行聚类:
library(cluster)
Heatmap(mat, name = "mat", cluster_rows = diana(mat),
cluster_columns = agnes(t(mat)), column_title = "clustering objects")
直接提供函数名:
# if cluster_columns is set as a function, you don't need to transpose the matrix
Heatmap(mat, name = "mat", cluster_rows = diana,
cluster_columns = agnes, column_title = "clustering functions")
上面命令和下面代码等价:
# code only for demonstration
Heatmap(mat, name = "mat", cluster_rows = function(m) as.dendrogram(diana(m)),
cluster_columns = function(m) as.dendrogram(agnes(m)),
column_title = "clutering functions")
请注意,当 cluster_rows 设置为函数时,参数 m 是输入 mat 本身,而对于 cluster_columns,m 是 mat 的转置。
这是一种特殊情况,你可能已经对矩阵行或列进行了分类,而只想对同一组中的执行聚类。可以通过分组变量拆分热图,也可以使用 cluster_within_group()
聚类函数生成特殊的树状图:
group = kmeans(t(mat), centers = 3)$cluster
Heatmap(mat, name = "mat", cluster_columns = cluster_within_group(mat, group))
在上面的例子中,同一组中的列仍然是聚类的,但是树状图变为为一条扁平线。列上的树状图显示了组的层次结构。
渲染聚类树
如果要渲染树状图,通常需要生成一个 dendrogram 对象,并提前通过 nodePar
和 edgePar
参数渲染,然后将其发送到 cluster_rows
或 cluster_columns
参数。
可以通过 dendextend
包渲染树状图对象,以对树状图进行更自定义的可视化:
library(dendextend)
row_dend = as.dendrogram(hclust(dist(mat)))
row_dend = color_branches(row_dend, k = 2) # `color_branches()` returns a dendrogram object
Heatmap(mat, name = "mat", cluster_rows = row_dend)
row_dend_gp
和 column_dend_gp
控制树状图的全局图形设置。注意:例如 row_dend 中的图形设置将被 row_dend_gp 覆盖:
Heatmap(mat, name = "mat", cluster_rows = row_dend, row_dend_gp = gpar(col = "red"))
从 2.5.6 版本开始,您还可以通过设置适当的 nodePar 在树状图的节点上添加图形:
row_dend = dendrapply(row_dend, function(d) {
attr(d, "nodePar") = list(cex = 0.8, pch = sample(20, 1), col = rand_color(1))
return(d)
})
Heatmap(mat, name = "mat", cluster_rows = row_dend, row_dend_width = unit(2, "cm"))
树状图重新排序
row_dend_reorder
和 column_dend_reorder
控制是否把树状图重新排序。如果这两个参数设置为 数字向量 ,则它们还控制重新排序的权重(它将被发送到 reorder.dendrogram() 的 wts 参数)。可以通过设置例如:关闭重新排序 row_dend_reorder = FALSE
。
默认情况下,如果 cluster_rows/cluster_columns 设置为 逻辑值 或 聚类函数,则树状图重新排序将打开。如果 cluster_rows/cluster_columns 设置为 聚类对象,则关闭:
m2 = matrix(1:100, nr = 10, byrow = TRUE)
Heatmap(m2, name = "mat", row_dend_reorder = FALSE, column_title = "no reordering")
Heatmap(m2, name = "mat", row_dend_reorder = TRUE, column_title = "apply reordering")
还有许多其他方法可以重新排序树状图,例如 dendsort 包。基本上,所有这些方法仍然返回一个经过重新排序的树状图对象,因此,我们可以首先根据数据矩阵生成行或列树状图,通过某种方法重新排序,并将其分配回 cluster_rows
或 cluster_columns
。
Heatmap(mat, name = "mat", column_title = "default reordering")
library(dendsort)
row_dend = dendsort(hclust(dist(mat)))
col_dend = dendsort(hclust(dist(t(mat))))
Heatmap(mat, name = "mat", cluster_rows = row_dend, cluster_columns = col_dend,
column_title = "reorder by dendsort")
收官!
代码 我上传到 QQ 群 老俊俊生信交流群
文件夹里。欢迎加入。加我微信我也拉你进 微信群聊 老俊俊生信交流群
哦。
群二维码:
老俊俊微信:
知识星球:
所以今天你学习了吗?
欢迎小伙伴留言评论!
今天的分享就到这里了,敬请期待下一篇!
最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!
如果觉得对您帮助很大,赏杯快乐水喝喝吧!
推 荐 阅 读