前言
我們繼續(xù)介紹 ComplexHeatmap
允扇,今天要介紹的內(nèi)容是熱圖列表遣妥。
ComplexHeatmap
包的一個重要的功能是传蹈,能夠在水平或豎直方向連接多個熱圖和注釋距境,以圖形化的方式展示各信息之間的關(guān)聯(lián)
通常水平方向的連接比較常用,我們介紹的重點(diǎn)也是水平連接祭阀,豎直的連接原理基本是一致的鹉戚。
在進(jìn)行水平連接時鲜戒,熱圖和注釋的行數(shù)要相同
例如,我們要繪制三個熱圖列表崩瓤,數(shù)據(jù)如下
set.seed(123)
mat1 <- matrix(rnorm(80, 2), 8, 10)
mat1 <- rbind(mat1, matrix(rnorm(40, -2), 4, 10))
rownames(mat1) <- paste0("R", 1:12)
colnames(mat1) <- paste0("C", 1:10)
mat2 <- matrix(runif(60, max = 3, min = 1), 6, 10)
mat2 <- rbind(mat2, matrix(runif(60, max = 2, min = 0), 6, 10))
rownames(mat2) <- paste0("R", 1:12)
colnames(mat2) <- paste0("C", 1:10)
le <- sample(letters[1:3], 12, replace = TRUE)
names(le) <- paste0("R", 1:12)
使用 +
以水平方向連接熱圖
ht1 <- Heatmap(mat1, name = "rnorm")
ht2 <- Heatmap(mat2, name = "runif")
ht3 <- Heatmap(le, name = "letters")
ht1 + ht2 + ht3
默認(rèn)情況下袍啡,第二幅熱圖的行樹狀圖會刪除,并且其行順序與第一幅熱圖一樣却桶,同時第一境输、二幅圖的行名也被刪除
連接操作會返回 HeatmapList
對象,直接打印 ht_list
會調(diào)用 draw
函數(shù)
> ht_list <- ht1 + ht2 + ht3
> class(ht_list)
[1] "HeatmapList"
attr(,"package")
[1] "ComplexHeatmap"
可以連接任意數(shù)量的熱圖颖系,或者往熱圖列表中添加熱圖
ht1 + ht_list
ht_list + ht1
ht_list + ht_list
還可以將 NULL
添加到熱圖列表嗅剖,適用于在循環(huán)外部設(shè)置一個空熱圖列表
ht_list <- NULL
for(s in sth) {
ht_list = ht_list + Heatmap(...)
}
Heatmap(...) + NULL
將會返回一個熱圖列表對象
1. 標(biāo)題
單個熱圖的標(biāo)題,可以在 Heatmap
函數(shù)內(nèi)置指定嘁扼,而熱圖列表的標(biāo)題信粮,需要在 draw
中進(jìn)行設(shè)置
例如
# 首先,我們分別為三個熱圖設(shè)置顏色
col_rnorm <- colorRamp2(c(-3, 0, 3), c("#f46d43", "#ffffbf", "#3288bd"))
col_runif <- colorRamp2(c(0, 1.5, 3), c("#de77ae", "#f7f7f7", "#7fbc41"))
col_letters <- c("a" = "#33a02c", "b" = "#fb9a99", "c" = "#e31a1c")
# 分別在 Heatmap 函數(shù)內(nèi)設(shè)置單個熱圖標(biāo)題
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_title = "Heatmap 1",
column_title = "Heatmap 1")
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
row_title = "Heatmap 2",
column_title = "Heatmap 2")
ht3 <- Heatmap(le, name = "letters",
col = col_letters)
ht_list <- ht1 + ht2 + ht3
# 設(shè)置熱圖列表的標(biāo)題
draw(
ht_list,
row_title = "Three heatmaps, row title",
row_title_gp = gpar(col = "red"),
column_title = "Three heatmaps, column title",
column_title_gp = gpar(fontsize = 16)
)
我們可以看到趁啸,第二張熱圖的行名并未顯示
2. 設(shè)置大小
我們在之前的文章中已經(jīng)介紹過如何設(shè)置熱圖的大小强缘,即 width
、height
控制單個熱圖主體的寬度和高度不傅,heatmap_width
和 heatmap_height
控制所有熱圖(包括注釋)的總寬度和高度
可以指定一個或多個熱圖的寬度
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
width = unit(4, "cm")
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters,
width = unit(5, "mm")
)
ht1 + ht2 + ht3
如果 width
設(shè)置為數(shù)值旅掂,將會轉(zhuǎn)換為 null
單位
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
width = 6
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
width = 4
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters,
width = 1
)
ht1 + ht2 + ht3
3. 設(shè)置間隔
ht_gap
參數(shù)用于控制兩個熱圖之間的間隔,可以是一個單位值或向量單位值
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters
)
ht_list <- ht1 + ht2 + ht3
draw(ht_list,
ht_gap = unit(1, "cm"))
draw(ht_list,
ht_gap = unit(c(3, 10), "mm"))
4. 自動調(diào)整熱圖主體
在熱圖列表中始終有一個主熱圖访娶,用于控制全局的行順序商虐,其他所有的熱圖會根據(jù)主熱圖的配置自動進(jìn)行調(diào)整,調(diào)整方式為:
- 不對行進(jìn)行聚類崖疤,按照主熱圖的行順序排列
- 刪除行標(biāo)題
- 如果主熱圖進(jìn)行了分割秘车,也會進(jìn)行分割
- 主熱圖的高度就是所有熱圖的高度
默認(rèn)第一張熱圖為主熱圖,例如
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters
)
ht2 + ht1 + ht3
現(xiàn)在劫哼,ht2
為主熱圖叮趴,所以 ht1
的 row_km
被忽略了
可以在 draw
函數(shù)中使用 main_heatmap
參數(shù)指定主熱圖,可以是熱圖名或數(shù)值索引
ht_list <- ht2 + ht1 + ht3
draw(ht_list, main_heatmap = "rnorm")
# draw(ht_list, main_heatmap = 2)
默認(rèn)只在主熱圖的邊上繪制其行樹狀圖和行名沦偎,可以使用 row_dend_side
和 row_sub_title_side
參數(shù)來設(shè)置其放置位置疫向,例如
ht_list <- ht2 + ht1 + ht3
draw(ht_list, main_heatmap = "rnorm",
row_dend_side = "right",
row_sub_title_side = "left")
如果主熱圖不聚類,其他熱圖還是不會聚類
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2, cluster_rows = FALSE
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters
)
ht1 + ht2 + ht3
如果要顯示所有行名豪嚎,可以設(shè)置 auto_adjust = FALSE
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters
)
ht_list <- ht1 + ht2 + ht3
draw(ht_list, main_heatmap = "rnorm",
auto_adjust = FALSE)
5. 使用 draw 函數(shù)控制主熱圖
主熱圖的設(shè)置可以放在 Heatmap()
函數(shù)內(nèi)部,但是在 draw()
函數(shù)內(nèi)設(shè)置會更方便些谈火,避免更改主熱圖時侈询,需要重新設(shè)置參數(shù),且 draw
的優(yōu)先級更高
draw
函數(shù)中控制主熱圖行順序的參數(shù)有:
cluster_rows
clustering_distance_rows
clustering_method_rows
row_dend_width
show_row_dend
row_dend_reorder
row_dend_gp
row_order
控制行切片的參數(shù)
row_gap
row_km
row_km_repeats
row_split
控制高度
height
heatmap_height
例如
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2, cluster_rows = FALSE)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif)
ht3 <- Heatmap(
le, name = "letters", col = col_letters)
ht_list <- ht1 + ht2 + ht3
draw(
ht_list, row_km = 1, row_split = le,
cluster_rows = TRUE)
Heatmap
函數(shù)內(nèi)的 row_km = 2, cluster_rows = FALSE
會被 draw
覆蓋
6. 注釋的調(diào)整
如果熱圖列表中某些熱圖帶有注釋糯耍,并且扔字,不同熱圖的注釋的高度是不同的囊嘉。
熱圖注釋及樹狀圖的高度會自動進(jìn)行調(diào)整,但是簡單注釋的大小通常不會調(diào)整革为,除非設(shè)置 anno_simple_size
參數(shù)扭粱,或者設(shè)置全局變量 ht_opt$anno_simple_size
例如
ht1 = Heatmap(
mat1, name = "rnorm", col = col_rnorm,
top_annotation = HeatmapAnnotation(
foo1 = 1:10,
annotation_name_side = "left")
)
ht2 = Heatmap(
mat2, name = "runif", col = col_runif)
ht3 = Heatmap(
le, name = "letters", col = col_letters)
ht1 + ht2 + ht3
第二個熱圖的樹狀圖變高了
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
top_annotation = HeatmapAnnotation(
foo1 = 1:10, bar1 = anno_points(1:10),
annotation_name_side = "left")
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
top_annotation = HeatmapAnnotation(
bar2 = anno_barplot(1:10)))
ht3 <- Heatmap(
le, name = "letters", col = col_letters)
ht_list <- ht1 + ht2 + ht3
draw(ht_list, ht_gap = unit(c(6, 2), "mm"))
在這個例子中,兩幅熱圖都有注釋震檩,由于簡單注視的大小不變琢蛤,所有調(diào)整了第二幅熱圖的復(fù)雜熱圖的高度,使兩幅熱圖的注釋高度一致
如果第一幅熱圖只有簡單注釋抛虏,則會調(diào)整樹狀圖的高度
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
top_annotation = HeatmapAnnotation(
foo1 = 1:10,
annotation_name_side = "left")
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
top_annotation = HeatmapAnnotation(
bar2 = anno_barplot(1:10)))
ht3 <- Heatmap(
le, name = "letters", col = col_letters)
ht_list <- ht1 + ht2 + ht3
draw(ht_list, ht_gap = unit(c(6, 2), "mm"))
如果兩幅熱圖都只包含簡單注釋博其,但是注釋的數(shù)量不同,則還是會調(diào)整樹狀圖的高度
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
top_annotation = HeatmapAnnotation(
foo1 = 1:10,
annotation_name_side = "left")
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif,
top_annotation = HeatmapAnnotation(
bar2 = cbind(
b1 = 1:10, b2 = 11:20, b3 = 21:30))
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters)
ht_list <- ht1 + ht2 + ht3
draw(ht_list, ht_gap = unit(c(6, 2), "mm"))
如果你想讓簡單注釋的大小也自動調(diào)整迂猴,可以在 HeatmapAnnotation()
函數(shù)中設(shè)置 simple_anno_size_adjust = TRUE
如果第一幅熱圖的注釋在底部慕淡,第二幅熱圖沒有注釋,則第二幅熱圖的列名直接放置在熱圖主體下方
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
bottom_annotation = HeatmapAnnotation(
foo1 = 1:10, bar1 = anno_points(1:10),
annotation_name_side = "left")
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ht3 <- Heatmap(
le, name = "letters", col = col_letters)
ht_list <- ht1 + ht2 + ht3
draw(ht_list, ht_gap = unit(c(6, 2), "mm"))
7. 熱圖與注釋串聯(lián)
行注釋可以添加到水平熱圖列表中沸毁,例如
ha1 <- rowAnnotation(
foo = 1:12, bar = anno_barplot(
1:12, width = unit(4, "cm"))
)
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2)
ht1 + ha1
上面的注釋可以分割為兩個獨(dú)立的行注釋
Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2) +
rowAnnotation(foo = 1:12) +
rowAnnotation(
bar = anno_barplot(1:12, width = unit(4, "cm"))
)
輸出的結(jié)果是一樣的
可是峰髓,行名怎么沒了?我要怎么顯示行名呢息尺?
有兩種方法:
- 將注釋放在
Heatmap
函數(shù)中
ha1 <- rowAnnotation(
foo = 1:12, bar = anno_barplot(
1:12, width = unit(4, "cm"))
)
Heatmap(
mat1, name = "rnorm", col = col_rnorm,
row_km = 2, right_annotation = ha1
)
- 或者將行名作為文本注釋添加
ht1 + ha1 +
rowAnnotation(rn = anno_text(
rownames(mat1), just = "left",
location = unit(0, "npc")))
通常携兵,熱圖和行注釋可以以任意的次序連接。例如掷倔,將注釋添加到左邊和中間
rowAnnotation(foo = 1:12) +
Heatmap(
mat1, name = "rnorm",
col = col_rnorm, row_km = 2) +
rowAnnotation(
bar = anno_barplot(1:12,
width = unit(4, "cm"))) +
Heatmap(mat2, name = "runif",
col = col_runif)
8. 注釋之間的串聯(lián)
可以只串聯(lián)注釋眉孩,而不需要熱圖參與
rowAnnotation(foo = 1:12) +
rowAnnotation(
bar = anno_barplot(
1:12, width = unit(4, "cm"))
)
如果只有一個注釋,必須要添加一個 NULL
rowAnnotation(
bar = anno_barplot(
1:12, width = unit(4, "cm"))
) + NULL
事實(shí)上勒葱,注釋列表本質(zhì)上是一個熱圖列表
anno_list <- rowAnnotation(foo = 1:12) +
rowAnnotation(
bar = anno_barplot(
1:12, width = unit(4, "cm"))
)
> class(anno_list)
[1] "HeatmapList"
attr(,"package")
[1] "ComplexHeatmap"
所以浪汪,你可以使用 draw()
函數(shù)來繪制
draw(anno_list,
row_split = rep(c("A", "B"), each = 6))
9. 豎直連接
使用 %v%
操作,可以以豎直的方式連接熱圖和注釋凛虽,其他設(shè)置基本上是類似的
下面死遭,列舉幾個例子
mat1t <-t(mat1)
mat2t <- t(mat2)
ht1 <- Heatmap(
mat1t, name = "rnorm", col = col_rnorm,
row_title = "rnorm")
ht2 <- Heatmap(
mat2t, name = "runif", col = col_runif,
row_title = "runif")
ht3 <- Heatmap(
rbind(letters = le), name = "letters",
col = col_letters)
ht_list <- ht1 %v% ht2 %v% ht3
draw(ht_list)
設(shè)置分塊
draw(ht_list, column_km = 2)
注釋放中間
ha <- HeatmapAnnotation(
foo = anno_barplot(1:12, height = unit(2, "cm"))
)
ht_list = ht1 %v% ha %v% ht2 %v% ht3
draw(ht_list, column_km = 2)
將熱圖分塊
ht1 <- Heatmap(
mat1t, name = "rnorm", col = col_rnorm,
row_km = 2)
ht2 <- Heatmap(
mat2t, name = "runif", col = col_runif,
row_km = 2)
ht3 <- Heatmap(
rbind(letters = le), name = "letters",
col = col_letters)
ha <- HeatmapAnnotation(
foo = anno_barplot(1:12, height = unit(2, "cm"))
)
ht_list <- ht1 %v% ha %v% ht2 %v% ht3
draw(ht_list, column_km = 2)
行注釋大小的調(diào)整與列注釋一樣
ht1 <- Heatmap(
mat1t, name = "rnorm", col = col_rnorm,
row_km = 2, left_annotation = rowAnnotation(
foo1 = 1:10, bar1 = anno_barplot(1:10))
)
ha <- HeatmapAnnotation(
foo = anno_barplot(
1:12, height = unit(2, "cm"),
axis_param = list(side = "right"))
)
ht2 <- Heatmap(
mat2t, name = "runif", col = col_runif,
row_km = 2, left_annotation = rowAnnotation(foo2 = 1:10))
ht3 <- Heatmap(
rbind(letters = le), name = "letters",
col = col_letters)
ht_list = ht1 %v% ha %v% ht2 %v% ht3
draw(ht_list, column_km = 2)
10. 熱圖列表子集
與 Heatmap
對象類似,熱圖列表也可以進(jìn)行切片操作凯旋。
對于水平熱圖列表呀潭,行索引對應(yīng)所有熱圖和注釋的行,列索引為相應(yīng)的熱圖或注釋名稱至非。例如
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm,
left_annotation = rowAnnotation(
foo1 = 1:12, bar1 = anno_points(1:12))
)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif
)
ha <- rowAnnotation(
foo2 = anno_barplot(1:12), bar2 = 12:1
)
ht_list <- ht1 + ht2 + ha
獲取熱圖列表包含的熱圖和注釋名稱
> names(ht_list)
[1] "rnorm" "runif" "foo2" "bar2"
獲取子集
ht_list[1:6, c("rnorm", "bar2")]
對于豎直熱圖列表也是類似的钠署。
11. 獲取次序和樹狀圖
row_order()
和 column_order()
可以獲取熱圖列表的行列順序。
記住:是對 draw
函數(shù)的返回對象進(jìn)行操作
例如荒椭,對于如下熱圖列表
ht1 <- Heatmap(
mat1, name = "rnorm", col = col_rnorm)
ht2 <- Heatmap(
mat2, name = "runif", col = col_runif)
ht_list <- ht1 + ht2
ht_list <- draw(ht_list)
行順序
> row_order(ht_list)
[1] 3 6 4 5 2 1 7 8 10 9 11 12
列順序
> column_order(ht_list)
$rnorm
[1] 5 2 7 6 10 1 9 8 4 3
$runif
[1] 4 10 2 5 7 6 1 3 8 9
如果未分塊熱圖谐鼎,返回的是 list
row_dend()
和 column_dend()
可以獲取行列樹狀圖.
12. 全局參數(shù)
ht_opt()
函數(shù)用于控制全局參數(shù),可以使用該函數(shù)為所有熱圖和注釋設(shè)置參數(shù)值
獲取所有全局參數(shù)
> ht_opt
Option Value
-----------------------:-------
heatmap_row_names_gp NULL
heatmap_column_names_gp NULL
heatmap_row_title_gp NULL
heatmap_column_title_gp NULL
legend_title_gp NULL
legend_title_position NULL
legend_labels_gp NULL
legend_grid_height NULL
legend_grid_width NULL
legend_border NULL
heatmap_border NULL
annotation_border NULL
fast_hclust FALSE
show_parent_dend_line TRUE
verbose FALSE
show_vp FALSE
simple_anno_size 5mm
DENDROGRAM_PADDING 0.5mm
DIMNAME_PADDING 1mm
TITLE_PADDING 2.5mm
COLUMN_ANNO_PADDING 1mm
ROW_ANNO_PADDING 1mm
這些參數(shù)都是見名知意的趣惠,不需要再做說明了
獲取這些參數(shù)值的方式狸棍,可以是
> ht_opt("heatmap_row_names_gp")
NULL
> ht_opt$heatmap_row_names_gp
NULL
設(shè)置參數(shù)值
ht_opt("heatmap_row_names_gp" = gpar(fontsize = 8))
ht_opt$heatmap_row_names_gp <- gpar(fontsize = 8)
實(shí)例
ht_opt(
heatmap_column_names_gp = gpar(fontface = "italic"),
heatmap_column_title_gp = gpar(fontsize = 10),
legend_border = "black",
heatmap_border = TRUE,
annotation_border = TRUE
)
ht1 <- Heatmap(
mat1, name = "ht1", column_title = "Heatmap 1",
top_annotation = HeatmapAnnotation(foo = 1:10)
)
ht2 <- Heatmap(
mat2, name = "ht2", column_title = "Heatmap 2",
top_annotation = HeatmapAnnotation(bar = 1:10)
)
ht1 + ht2
繪制完之后身害,應(yīng)該重置參數(shù)值
ht_opt(RESET = TRUE)
13. 設(shè)置邊距
draw
函數(shù)中的 padding
參數(shù)可以設(shè)置繪圖塊四周的邊距,padding
參數(shù)接受長度為 4
的向量草戈,分別代表圖像的下塌鸯、左、上唐片、右的邊距
例如丙猬,對于行名較長的熱圖,會出現(xiàn)顯示不全的問題
m <- matrix(rnorm(100), 10)
rownames(m) <- paste0("R", 1:10)
rownames(m)[1] = "a long long long long long row name"
ht <- Heatmap(
m, name = "mat", row_names_side = "left",
show_row_dend = FALSE
)
draw(ht)
添加邊距
draw(ht, padding = unit(c(2, 20, 2, 2), "mm"))