前言
使用 pheatmap
已经能够绘制满足大多数要求的聚类热图了。
受 pheatmap
包的启发,ComplexHeatmap
提供了对热图更多更灵活的控制,如多数据热图的排列比较以及多种图形注释等。
下面我们详细介绍 ComplexHeatmap
包
设计理念
一张热图分为主体和组件两部分,热图的主体可以分割为多行多列的热图块,热图的组件包括标题、树状图、行列名以及注释,这些组件可以分布在主体的上下左右四个方向,如下图
而对于多个热图列表的排列,分为水平排列和竖直排列两种方式,标题和图例放置在四周,行列注释跟随在热图之后
ComplexHeatmap
包是基于 grid
包的,使用面向对象的方式实现热图及其组件,主要包含以下几个类:
-
Heatmap
:绘制单个热图 -
HeatmapList
:绘制热图列表 -
HeatmapAnnotation
:定义热图的行、列注释列表,可以是热图的一部分,也可以独立于热图
以及一些内部类:
-
SingleAnnotation
:定义单个行、列注释,组成HeatmapAnnotation
的列表元素 -
ColorMapping
:定义值到颜色的映射 -
AnnotationFunction
:用于自定义注释图形
绘制热图
安装导入
install.packages("ComplexHeatmap")
library(ComplexHeatmap)
我们还是使用上次的数据
> data <- as.matrix(read.csv("~/Downloads/RPKM_DEG.csv", row.names = 1))
> head(data)
control1 control2 control3 treat1 treat2 treat3
Gene1 178.413 180.616 111.951 44.264 44.251 35.842
Gene2 1790.491 33.799 3076.195 533.618 527.694 493.286
Gene3 55.313 72.512 42.625 26.291 31.324 26.485
Gene4 138.170 10.234 168.461 1014.917 968.487 1013.409
Gene5 400.783 417.081 422.252 16.958 21.532 18.350
Gene6 16.466 10.856 17.788 117.155 113.056 117.383
由于 ComplexHeatmap
包并不会对数据进行标准化,为了让图形更好看,我们先手动对数据进行标准化
exp <- apply(data, 1, scale)
rownames(exp) <- colnames(data)
exp <- t(exp)
绘制热图
Heatmap(data)
在我们不设置参数的情况下,图片长这样,不太好看。
1. 配色
通常,我们绘制的矩阵都是连续型数据,因此颜色映射函数需要接受一个向量输入,并返回一个向量输出
该包的作者推荐使用他写的另一个包 circlize
的函数 colorRamp2
来设置颜色映射,colorRamp2
函数接受两个参数,第一个参数用来设置值映射范围断点,第二个参数用于设置对应的颜色值
例如
library(circlize)
col_fun <- colorRamp2(
c(-2, 0, 2),
c("#8c510a", "white", "#01665e")
)
我们限定值为 -2
映射为 green
,0
映射为 white
,2
映射为 red
。
在这之间的值以线性内插的方式获取到相应的值,如果值超出了 [-2,2]
范围
> col_fun(seq(-3, 3))
[1] "#8C510AFF" "#8C510AFF" "#CCA482FF" "#FFFFFFFF" "#8BB0ABFF" "#01665EFF" "#01665EFF"
可以看到,超出范围的值都被赋值为了临界值
现在,我们可以重新绘制不同颜色的热图
Heatmap(exp, name = "expression", col = col_fun)
name
参数的作用是设置颜色图例的名称
颜色并不会受异常值的影响,但是会影响聚类的结果,例如,我们添加一个很大的值
mat <- exp
mat[1, 1] <- -100000
Heatmap(mat, name = "expression", col = col_fun)
如果矩阵的值是连续型的,也可以提供一个颜色向量,但是向量的前后两个值会对应到矩阵的最小值和最大值,因此,会受异常值的影响。
Heatmap(exp, name = "expression", col = rainbow(10))
这种方式等价于
col = colorRamp2(seq(min(exp), max(exp), length = 10), rainbow(10))
而对于矩阵为离散型数值,需要将颜色设置为命名向量,名称与矩阵的值相对应,例如
discrete_mat <- matrix(
sample(1:4, 100, replace = TRUE),
10, 10
)
colors <- structure(
rainbow(4),
names = c("1", "2", "3", "4")
)
Heatmap(
discrete_mat,
name = "expression",
col = colors
)
我们使用 structure
来定义一个命名向量,如果向量的值不是颜色值,会自动映射到颜色
如果矩阵的值为字符型,绘制方法也是类似
discrete_mat <- matrix(
sample(LETTERS[1:4], 100, replace = TRUE),
10, 10
)
colors <- structure(
rainbow(4),
names = LETTERS[1:4]
)
Heatmap(
discrete_mat,
name = "expression",
col = colors
)
但是,我们可以看到,对于字符型的矩阵不会进行聚类,如果想要对其进行聚类,需要传递相应的距离度量
如果矩阵中存在 NA
值,可以使用 na_col
参数来设置 NA
值的颜色
mat_with_na <- exp
na_index <- sample(
c(TRUE, FALSE),
nrow(exp)*ncol(exp),
replace = TRUE,
prob = c(1, 9)
)
mat_with_na[na_index] <- NA
Heatmap(
mat_with_na,
name = "expression",
col = col_fun,
na_col = "black"
)
默认情况下,颜色的线性内插的方式是遵循 LAB
颜色空间的变化,还有其他的颜色空间可供选择,如
热图的最外层边框使用 border
参数设置,网格线使用 rect_gp
参数来设置
border
参数可以是逻辑值或颜色值,而 rect_gp
参数需要接受一个 grid::gpar
对象,
Heatmap(
exp,
name = "expression",
border = "black",
col = col_fun,
rect_gp = gpar(col = "white", lwd = 2)
)
rect_gp
还支持一个非标准参数 type
,如果设置为 none
,则不会绘制中间的热图主体,但是可以使用 cell_fun
或 layer_fun
添加自定义图形
Heatmap(
exp,
name = "expression",
rect_gp = gpar(type = "none")
)
2. 标题
标题设置比较简单,我们设置列标题的样式
Heatmap(
exp,
col = col_fun,
name = "expression",
column_title = "sample",
column_title_side = "bottom",
column_title_rot = 0,
column_title_gp = gpar(
col = "red",
fontsize = 18,
fontface = "italic",
fill = "green",
border = "black"
)
)
对于行标题也是类似的
Heatmap(
exp,
col = col_fun,
name = "expression",
row_title = "Genes",
row_title_side = "left",
row_title_rot = 90,
row_title_gp = gpar(
col = "red",
fontsize = 18,
fontface = "italic",
fill = "green",
border = "black"
)
)
标题的内容支持表达式格式
Heatmap(
exp,
name = "expression",
col = col_fun,
column_title = expression(
hat(beta) == (X^t * X)^{-1} * X^t * y
)
)
如果想要设置更复杂的文本内容,可以使用 gridtext
包对文本进行渲染
3. 聚类
ComplexHeatmap
包中的层次聚类有很大的灵活性,可以有多种方法来指定
- 现有的距离度量(如
euclidean
、pearson
等) - 自定义距离函数
- 聚类函数
- 聚类对象(
hclust
或dendrogram
)
3.1 距离度量
距离度量的指定有三种方式:
- 现有度量,如
dist()
函数包含的各种度量函数 - 自定义的计算矩阵距离度量的函数
- 自定义的计算两个向量之间距离度量的函数
例如,spearman
相关
Heatmap(
exp,
col = col_fun,
name = "expression",
clustering_distance_rows = "spearman"
)
自定义计算矩阵度量函数
Heatmap(
exp,
col = col_fun,
name = "expression",
clustering_distance_rows = function(m) dist(m)
)
自定义两个向量相关性函数
Heatmap(
exp,
col = col_fun,
name = "expression",
clustering_distance_rows = function(x, y) 1 - cor(x, y)
)
基于自定义函数的方法,我们可以定义一个度量函数,在计算两个向量的度量之前,去除数据中的离群点,使距离更稳定。例如
robust_dist = function(x, y) {
# 计算 0.1 和 0.9 分位数
qx = quantile(x, c(0.1, 0.9))
qy = quantile(y, c(0.1, 0.9))
# 只取 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))
}
聚类
col_fun <- colorRamp2(
c(-2, 0, 2),
c("#ff7f00", "white", "#1f78b4")
)
mat <- exp
mat[sample(1:20, 7), sample(1:6, 1)] <- -100000
Heatmap(mat, name = "expression", col = col_fun,
clustering_distance_rows = robust_dist,
clustering_distance_columns = robust_dist)
我们也可以定义字符向量之间的距离度量函数,来对字符型矩阵进行聚类
首先,定义字符向量之间的距离度量,将字符转换为 · 码数值,然后计算欧氏距离
dist_letters <- function(x, y) {
# 使用 utf8ToInt 将 utf-8 字符串转换为 ASCII 码向量
x = utf8ToInt(paste(x, collapse = ""))
y = utf8ToInt(paste(y, collapse = ""))
sqrt(sum((x - y)^2))
}
绘制热图
Heatmap(
discrete_mat, name = "mat",
# 定义离散值颜色映射
col = structure(3:6, names = LETTERS[1:4]),
# 对行列应用度量函数
clustering_distance_rows = dist_letters,
clustering_distance_columns = dist_letters,
# 显示单元格文本
cell_fun = function(j, i, x, y, w, h, col) {
grid.text(discrete_mat[i, j], x, y) }
)
3.2 聚类函数
层次聚类的聚类方法与 hclust()
函数一样,使用 clustering_method_rows
和 clustering_method_columns
两个参数来分别指定行列的聚类方法
Heatmap(
exp, name = "expression",
col = col_fun,
clustering_method_rows = "single"
)
或者使用其他包的聚类函数,如 cluster
包
library(cluster)
Heatmap(
exp, name = "expression",
col = col_fun,
cluster_rows = diana,
cluster_columns = agnes
)
如果需要绘制的热图比较多,可以使用快速版的 hclust
,通过设置全局变量来开启
ht_opt$fast_hclust = TRUE
3.3 树状图渲染
树状图的渲染需要使用 dendextend
包来创建一个 dendrogram
对象,下面我们只简单介绍一下
library(dendextend)
# 创建 dendrogram 对象
col_dend <- as.dendrogram(hclust(dist(t(exp))))
# 添加颜色分支
col_dend <- color_branches(col_dend, k = 2)
Heatmap(
exp, name = "expression",
col = col_fun,
# 直接传递给 cluster_columns 参数
cluster_columns = col_dend
)
注意,我们在聚类的时候对矩阵进行了转置,表示对矩阵的列进行聚类,对行进行聚类不需要转置
也可以使用 row_dend_gp
和 column_dend_gp
参数来设置树形图的图形属性
Heatmap(
exp, name = "expression",
col = col_fun,
cluster_columns = col_dend,
column_dend_gp = gpar(
col = "red")
)
3.4 树状图重排
row_dend_reorder
和 column_dend_reorder
用于控制是否对树形图进行重排,默认值为
row_dend_reorder = is.logical(cluster_rows) || is.function(cluster_rows)
column_dend_reorder = is.logical(cluster_columns) || is.function(cluster_columns)
即,如果 cluster_rows/columns
为逻辑值或函数,会对树状图重排,而如果是聚类对象,则不会对树状图重排
4. 设置行列顺序
我们可以使用 row_order
和 column_order
参数自定义行列的顺序,但意味着将不会再对数据进行聚类
Heatmap(
exp, name = "expression",
col = col_fun,
column_order = order(colnames(exp)),
row_order = order(as.numeric(gsub("Gene", "", rownames(exp))))
)
或者,之间传递字符向量
Heatmap(
exp, name = "expression",
col = col_fun,
column_order = order(colnames(exp)),
row_order = rownames(exp)
)
还可以与 Seriation
包结合使用,利用 Seriation
提供的函数和方法,对矩阵的行列进行排序,然后获取相应的顺序,并设置到对应的参数上。
5. 设置行列名称
设置行列名称相关的参数包括
-
show_row/column_names
:是否显示行/列标签 -
row/column_labels
:重置行/列标签 -
row/column_names_side
:标签放置位置 -
row/column_names_gp
:图形属性 -
row/column_names_centered
:居中对齐 -
row/column_names_max_width
:最大宽度 -
row/column_names_rot
:旋转角度
Heatmap(
exp, name = "expression",
col = col_fun,
# 行标签放在左边
row_names_side = "left",
# 让行树状图去右边
row_dend_side = "right",
# 居中对齐
row_names_centered = TRUE,
# 设置选择角度
row_names_rot = 45,
# 设置行标签字体大小
row_names_gp = gpar(
col = "#1f78b4",
fontsize = 16
),
# 设置列标签颜色
column_names_gp = gpar(
col = c(rep("#de77ae", 3), rep("#7fbc41", 3))
)
)
有时候,我们的行名或者列名比较长,例如
mat <- exp
rownames(mat)[5] <- paste(c(letters, LETTERS), collapse = "")
Heatmap(
mat, name = "expression",
col = col_fun,
)
默认大小为 6
厘米,我们可以设置行名或列名的最大宽度
对于基因表达分析,我们的行名通常会设置为 gene ID
,但是 ID
是不能让人直观地知道到底代表哪个基因,所以将 ID
转换为 Symbol
会利于阅读。
因此,row/column_labels
参数的重置标签是很有用的。同时,由于矩阵的行列名是不允许重复的,但是重置热图行列标签不会受这一规则限制,例如
row_labels <- structure(
paste0(
sample(letters, 20),
sample(1:9, 20, replace = TRUE)
),
names = rownames(exp)
)
Heatmap(
exp, name = "expression",
col = col_fun,
row_labels = row_labels
)
而且,还支持表达式作为行列名
Heatmap(
exp, name = "expression",
col = col_fun,
row_labels = row_labels,
column_labels = col_labels
)
6. 分割热图
ComplexHeatmap
支持按行或按列分割热图,对热图进行分组
6.1 k-means
使用 row_km
和 column_km
来对矩阵进行 k-means
分组,然后对分组聚类
Heatmap(
exp, name = "expression",
col = col_fun,
row_km = 3,
column_km = 2
)
Heatmap()
在内部调用的 kmeans()
算法是使用随机起始点的,因此,某些情况下,可能每次运行的结果不同,可以设置 *_km_repeats
来设置运行次数,并取一致的聚类结果
Heatmap(
exp, name = "expression",
col = col_fun,
row_km = 3,
column_km = 2,
row_km_repeats = 100,
column_km_repeats = 100
)
运行次数越多,速度越慢
你可能会好奇,树状图中的虚线代表什么,我们将矩阵进行分割后,在每个分组内进行了层次聚类,然后有使用分组内的均值来对分组进行层次聚类,虚线是标注各子树形图与父树形图
6.2 分类变量
row_split
和 column_split
参数可以设置分类向量或数据框来分隔热图,例如
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = rep(LETTERS[1:5], each = 4),
column_split = rep(LETTERS[6:7], each = 3)
)
数据框
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = data.frame(
rep(LETTERS[1:2], 10),
rep(LETTERS[24:25], each = 10)
)
)
事实上,k-means
聚类只是生成一个簇向量,然后添加到 row_split
或 column_split
参数中,我们可以混合二者
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = factor(rep(LETTERS[1:2], 10)),
row_km = 2
)
也可以传递其他聚类方法的结果
pa <- cluster::pam(exp, k = 3)
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = pa$clustering
)
如果同时还设置了 row_order
或 column_order
,则会分别在每个分组中进行排序,例如
Heatmap(
exp, name = "expression",
col = col_fun,
km = 2,
row_order = 20:1
)
对于字符矩阵,只能使用 row/column_split
来分隔热图
Heatmap(
discrete_mat, name = "expression",
col = 3:6,
row_split = discrete_mat[, 1]
)
6.3 按树形图分割
有时候,我们希望的是根据层次聚类的结果来对矩阵进行分割,而不是先分割再聚类,这时,可以为 row/column_split
设置单个数值
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = 3,
column_split = 2
)
6.4 热图块顺序
当设置了 k-means
聚类,或 row/column_split
参数值为分类变量或数据框,默认会对分块进行聚类,在这种情况下,是无法控制分块的顺序的
但是可以将 cluster_row/column_slices
参设置为 FALSE
来关闭分块聚类
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = factor(rep(LETTERS[1:2], 10), levels = LETTERS[1:2]),
column_split = factor(rep(LETTERS[24:25], each = 3), levels = LETTERS[24:25]),
cluster_row_slices = FALSE,
cluster_column_slices = FALSE
)
6.5 热图块的标题
在前面的例子中,我们对热图进行分块,每个热图块都有对应的标题,如果想要设置这些标题的名称要怎么做呢?
我们看到,如果分块变量为 1
个,则标题名称为该变量的 level
,如果分类变量有多个,则标题为 level1,level2,...
ComplexHeatmap
支持三种类型的模板文本,第一种 sprintf()
使用 %s
来替换对应的 level
,例如
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = data.frame(
rep(LETTERS[1:2], 10),
rep(LETTERS[24:25], each = 10)
),
row_title = "%s&%s"
)
以及 GetoptLong
包的 @{}
标记或 glue
的 {}
标记
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = data.frame(
rep(LETTERS[1:2], 10),
rep(LETTERS[24:25], each = 10)
),
# row_title = "@{map[ x[1] ]} and @{map[ x[2] ]}"
row_title = "{map[ x[1] ]} and {map[ x[2] ]}"
)
默认会旋转标题,我们将它转回来,只要添加 row_title_rot = 0
就行
row_title_rot = 0
也可以使用数值或者 *_km
Heatmap(
exp, name = "expression",
col = col_fun,
# row_km = 3,
row_split = 3,
row_title = "cluster_%s"
)
如果还要绘制全局的标题,则可以
hm <- Heatmap(
exp, name = "expression",
col = col_fun,
row_split = data.frame(
rep(LETTERS[1:2], 10),
rep(LETTERS[24:25], each = 10)
),
row_title = "%s&%s"
)
draw(hm, row_title = "Gene set")
6.6 热图块图形属性
要为热图块的行列标题或行列名称指定图形属性,可以传递一个与热图块数量相等的向量值
例如
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = 3,
column_split = 2,
row_title_gp = gpar(
col = rainbow(3),
font = 1:3
),
row_names_gp = gpar(
col = rainbow(3),
fontsize = 10:12
),
column_title_gp = gpar(
fill = rainbow(5)[4:5],
alpha = 0.5
),
column_names_gp = gpar(
col = rainbow(5)[4:5]
)
)
6.7 热图块间距
row/column_gap
可以控制热图块之间的间距,可以是单个值或向量
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = 3,
column_split = 2,
row_gap = unit(c(2, 4), "mm"),
column_gap = unit(2, "mm")
)
设置 border = TRUE
可以为每个热图块设置边框
Heatmap(
exp, name = "expression",
col = col_fun,
row_split = 3,
column_split = 2,
row_gap = unit(c(2, 4), "mm"),
column_gap = unit(2, "mm"),
border = TRUE
)
注意:分割热图时会将相应的热图注释也一并切开了
7. 自定义热图主体
热图主体默认是由不同颜色填充的矩形框组成,我们姑且称之为单元格。
我们可以使用 cell_fun
和 layer_fun
参数来自定义主体的图形样式
cell_fun
用于绘制每个单元格,layer_fun
是其矢量化的版本,cell_fun
使用简单,layer_fun
执行速度快,样式多
7.1 cell_fun
cell_fun
参数接受一个带 7 个参数的函数,分别是:
-
j
: 数据矩阵的列索引 -
i
: 数据矩阵的行索引 -
x
: 热图主体viewport
中对应的单元格中点x
坐标 -
y
: 热图主体viewport
中对应的单元格中点y
坐标 -
width
: 该单元格宽度 -
height
: 该单元格高度 -
fill
: 单元格填充色
在每个单元格中执行时,函数会自动接收到这 7
个参数值
我们可以将矩阵的值添加到热图中
cell_fun <- function(j, i, x, y, width, height, fill) {
grid.text(
round(exp[i, j], 2),
x, y,
gp = gpar(
fontsize = 10
))
}
Heatmap(
exp, name = "expression",
col = col_fun,
cell_fun = cell_fun
)
添加过滤,只显示正值
cell_fun <- function(j, i, x, y, width, height, fill) {
if (exp[i, j] > 0) {
grid.text(round(exp[i, j], 2),
x, y,
gp = gpar(fontsize = 10))
}
}
与热图分块无缝衔接
Heatmap(
exp, name = "expression",
col = col_fun,
cell_fun = cell_fun,
row_km = 3,
column_km = 2
)
我们可以使用 cell_fun
来绘制与 corrplot
类似的相关系数矩阵
cell_fun <- function(j, i, x, y, width, height, fill) {
grid.rect(x, y, width = width, height = height,
gp = gpar(col = "grey"))
if (i < j) {
grid.text(
round(exp[i, j], 2),
x, y,
gp = gpar(fontsize = 10)
)
} else if (i == j) {
grid.text(colnames(exp)[i], x, y)
} else {
grid.circle(
x, y,
r = abs(exp[i, j]) / 4 * min(width, height),
gp = gpar(
fill = col_fun(exp[i, j]),
col = NA
))
}
}
Heatmap(
exp[1:6,], name = "expression",
col = col_fun,
cell_fun = cell_fun,
show_row_names = FALSE,
show_column_names = FALSE,
cluster_rows = FALSE,
cluster_columns = FALSE
)
7.2 layer_fun
layer_fun
是按照热图块的方式添加图形,与 cell_fun
类似,也包含 7
个参数,但它们的值都是向量的形式
由于 i
和 j
都是向量,要获取其在矩阵中对应的值就不能直接用 mat[i,j]
的方式,因为行列坐标分别保存在 i
、j
向量的对应位置
例如
> mat <- matrix(1:9, nr = 3)
> mat[1:2, c(1, 3)]
[,1] [,2]
[1,] 1 7
[2,] 2 8
但其实我们要获取的是位于 (1,1)
和 (2,3)
的值
但可以使用 ComplexHeatmap
提供的函数 pindex()
> pindex(mat, 1:2, c(1, 3))
[1] 1 8
绘制 layer_fun 版
layer_fun <- function(j, i, x, y, w, h, f) {
grid.text(round(pindex(exp, i, j), 2),
x, y, gp = gpar(fontsize = 10))
}
Heatmap(
exp, name = "expression",
col = col_fun,
layer_fun = layer_fun
)
当热图被分割时,layer_fun
会应用于每个热图块中。我们可以为所有值之和大于 0
的热图块添加矩形框线
layer_fun <- function(j, i, x, y, w, h, f) {
vt <- pindex(exp, i, j)
grid.text(round(vt, 2),
x, y, gp = gpar(fontsize = 10))
if (sum(vt) > 0) {
grid.rect(
gp = gpar(
lwd = 2,
fill = NA,
col = "red")
)
}
}
Heatmap(
exp, name = "expression",
col = col_fun,
layer_fun = layer_fun,
row_split = 3,
column_split = 2
)
layer_fun
还可以接受两个额外的参数,即当前热图块的行列索引,例如
layer_fun <- function(j, i, x, y, w, h, f, r, c) {
vt <- pindex(exp, i, j)
grid.text(round(vt, 2),
x, y, gp = gpar(fontsize = 10))
if (r != c) {
grid.rect(
gp = gpar(
lwd = 2,
fill = NA,
col = "green")
)
}
}
Heatmap(
exp, name = "expression",
col = col_fun,
layer_fun = layer_fun,
row_split = 3,
column_split = 2
)
为行列索引不一致的热图块添加绿色框线
对于每个热图块,我们可能想要获取该热图块索引的矩阵形式,即将向量化的 i,j,x,y
参数,转换为对应热图块的矩阵形式。我们可以使用 restore_matrix()
函数
例如,直接将 4
个参数传递进去,它会返回与热图块维度相同的矩阵
ind_mat = restore_matrix(j, i, x, y)
例如,我们第一个热图块的大小是 8 行 3 列
[,1] [,2] [,3]
[1,] 1 9 17
[2,] 2 10 18
[3,] 3 11 19
[4,] 4 12 20
[5,] 5 13 21
[6,] 6 14 22
[7,] 7 15 23
[8,] 8 16 24
该矩阵的值对应其在 4
个参数中的位置
例如,我们可以在每个热图块的第一行第二列单元格绘制一个圆点
layer_fun <- function(j, i, x, y, w, h, f, r, c) {
ind_mat <- restore_matrix(j, i, x, y)
ind <- ind_mat[1, 2]
grid.points(
x[ind],
y[ind],
pch = 16,
size = unit(4, "mm"),
gp = gpar(col = "green"))
}
Heatmap(
exp, name = "expression",
col = col_fun,
layer_fun = layer_fun,
row_split = 3,
column_split = 2
)
8. 热图尺寸
width
和 height
用于控制热图主体的宽度和高度,heatmap_width
和 heatmap_height
控制整个热图的宽度和高度。
默认情况下,热图的组件都有固定宽度,而热图主体自动填充剩余区域
Heatmap(
exp, name = "expression",
col = col_fun,
width = unit(8, "cm"),
height = unit(8, "cm")
)
Heatmap(
exp, name = "expression",
col = col_fun,
heatmap_width = unit(14, "cm"),
heatmap_height = unit(14, "cm")
)
9. 热图绘制
在上面的例子中,我们都是直接使用 Heatmap
函数来绘制热图,但其实这只是在交互式模式下的行为,它本质上只是一个构造函数,如果你把 Heatmap
放置在
- 一个函数中
-
if
、for
代码块中、 - 脚本中,并在命令行运行
都不会有任何输出的
因为,上述情况下,都不会调用 show()
方法,也不会执行 draw()
方法。
所以绘制热图的正确方式是
ht <- Heatmap(...)
draw(ht)
draw()
函数实际上用于绘制热图列表,即 HeatmapList
类。单个热图 Heatmap
类的绘制只是将其转换为包含一个热图的 HeatmapList
,然后再调用 HeatmapList
的 draw
方法
10. 获取顺序及树状图
row_order()
和 column_order()
函数可以获取热图的行、列顺序
hm <- Heatmap(
exp, name = "expression",
col = col_fun
)
dhm <- draw(hm)
> row_order(hm)
[1] 13 18 9 5 19 20 16 3 7 17 1 2 8 12 4 6 15 14 11 10
> row_order(dhm)
[1] 13 18 9 5 19 20 16 3 7 17 1 2 8 12 4 6 15 14 11 10
> column_order(dhm)
[1] 2 1 3 6 5 4
虽然两种方法都可以,但还是有所区别
row_order(hm)
会先执行聚类,然后获取聚类的结果
row_order(dhm)
是获取图形输出中的行顺序
如果有添加 k-means
聚类,两次的结果有可能会不一致,推荐使用后一种方式。
如果有对热图进行拆分,获取顺序将会返回一列 list
hm <- Heatmap(
exp, name = "expression",
row_km = 3,
col = col_fun
)
hm <- draw(hm)
> row_order(hm)
$`1`
[1] 8 12 4 6 15 14 11 10
$`2`
[1] 16 3 7 17 19 5 20 1
$`3`
[1] 13 9 18 2
类似地,row_dend()
和 column_dend()
用于获取聚类的树形图,如果热图被分割,也会返回一个 list
11. 热图子集
Heatmap
对象可以用切片的方式获取聚类结果的子集
hm <- Heatmap(
exp, name = "expression",
row_km = 3,
col = col_fun
)
hm[1:6, 1:6]