ComplexHeatmap復(fù)雜熱圖繪制學(xué)習(xí)——3.熱圖注釋(一)

第 3 章 熱圖注釋

熱圖注釋是熱圖的重要組成部分惕医,它顯示與熱圖中的行或列相關(guān)聯(lián)的附加信息泞坦。 ComplexHeatmap包為設(shè)置注釋和定義新的注釋圖形提供了非常靈活的支持。注釋可以放在熱圖的四個側(cè)面,由top_annotation鲫构,bottom_annotationleft_annotationright_annotation參數(shù)組成玫坛。

接下來我們將對不同第注釋函數(shù)anno_*()進(jìn)行說明结笨,如空注釋anno_empty()、塊注釋anno_block()湿镀、圖像注釋anno_image()炕吸、點注釋anno_points()、線注釋anno_lines()勉痴、條形圖注釋anno_barplot()赫模、箱線圖注釋anno_boxplot()、直方圖注釋anno_histogram()蒸矛、密度注釋anno_density()等注釋方法瀑罗。

四個參數(shù)的值應(yīng)該在HeatmapAnnotation類中并且由HeatmapAnnotation()函數(shù)構(gòu)造,如果是行注釋則由rowAnnotation()函數(shù)構(gòu)造雏掠。(rowAnnotation()只是一個與HeatmapAnnotation(..., which = "row")相同的輔助函數(shù)) 斩祭,熱圖注釋的簡單用法如下。

set.seed(123)
mat = matrix(rnorm(100), 10)
rownames(mat) = paste0("R", 1:10)
colnames(mat) = paste0("C", 1:10)
column_ha = HeatmapAnnotation(foo1 = runif(10), bar1 = anno_barplot(runif(10)))
row_ha = rowAnnotation(foo2 = runif(10), bar2 = anno_barplot(runif(10)))
Heatmap(mat, name = "mat", top_annotation = column_ha, right_annotation = row_ha)
image

將熱圖注釋指定為底部注釋和左側(cè)注釋乡话。

Heatmap(mat, name = "mat", bottom_annotation = column_ha, left_annotation = row_ha)
image.png

在上面的例子中停忿,column_harow_ha都有兩個注釋,其中 foo1foo2是數(shù)字向量蚊伞,bar1bar2是條形圖。類似向量的注解在這里稱為“簡單注釋”吮铭,條形圖注解稱為“復(fù)雜注釋”时迫。您已經(jīng)可以看到注釋必須定義為名稱=值對(例如 foo = ...)。

熱圖注釋也可以獨立于熱圖谓晌。它們可以通過+(水平連接)或%v%(垂直連接)到熱圖列表掠拳。

# code only for demonstration
Heatmap(...) + rowAnnotation() + ...
Heatmap(...) %v% HeatmapAnnotation(...) + ...

HeatmapAnnotation()返回一個HeatmapAnnotation類對象。對象通常由幾個注釋組成纸肉。如以下部分溺欧,首先介紹單個注釋的設(shè)置,然后展示如何將它們組合在一起柏肪。

可以看到column_harow_ha對象的信息:

column_ha
## A HeatmapAnnotation object with 2 annotations
##   name: heatmap_annotation_0 
##   position: column 
##   items: 10 
##   width: 1npc 
##   height: 15.3514598035146mm 
##   this object is subsetable
##   5.92288888888889mm extension on the left 
##   9.4709mm extension on the right 
## 
##  name   annotation_type color_mapping height
##  foo1 continuous vector        random    5mm
##  bar1    anno_barplot()                 10mm
row_ha
## A HeatmapAnnotation object with 2 annotations
##   name: heatmap_annotation_1 
##   position: row 
##   items: 10 
##   width: 15.3514598035146mm 
##   height: 1npc 
##   this object is subsetable
##   9.96242222222222mm extension on the bottom 
## 
##  name   annotation_type color_mapping width
##  foo2 continuous vector        random   5mm
##  bar2    anno_barplot()                10mm

在本章的以下示例中姐刁,除非必要,否則我們將僅顯示沒有熱圖的注釋圖形烦味。如果你想用一個熱圖來試試吧聂使,你只需指定HeatmapAnnotation,我們是以ha名稱來作為top_annotationbottom_annotation柏靶,left_annotationright_annotation討論對象弃理。

列注釋和行注釋的設(shè)置基本相同。如果沒有什么特別的屎蜓,我們只以列注釋作為示例痘昌。如果您想嘗試一行注釋,只需添加which = "row"HeatmapAnnotation()或直接切換到rowAnnotation()功能炬转。

3.1簡單注釋

所謂的“簡單注釋”是最常用的注釋樣式辆苔,它是類似熱圖或類似網(wǎng)格的圖形,其中使用顏色映射到注釋值返吻。要生成一個簡單的注釋姑子,您只需簡單地將一個特定的名稱注釋向量放入HeatmapAnnotation()中。

ha = HeatmapAnnotation(foo = 1:10)
image

離散型數(shù)據(jù)注釋:

ha = HeatmapAnnotation(bar = sample(letters[1:3], 10, replace = TRUE))
image

除了HeatmapAnnotation()测僵,您可以使用任何字符串作為注釋名稱街佑。

如果未指定顏色,則隨機生成顏色捍靠。col設(shè)置注釋的顏色沐旨,col需要設(shè)置命名列表。

對于連續(xù)值注釋榨婆,顏色映射應(yīng)該是由 circlize::colorRamp2()生成的顏色映射函數(shù)磁携。

library(circlize)
col_fun = colorRamp2(c(0, 5, 10), c("blue", "white", "red"))
ha = HeatmapAnnotation(foo = 1:10, col = list(foo = col_fun))
image

對于離散注釋,顏色應(yīng)該是命名向量良风,其中名稱對應(yīng)于注釋中的級別谊迄。

ha = HeatmapAnnotation(bar = sample(letters[1:3], 10, replace = TRUE),
    col = list(bar = c("a" = "red", "b" = "green", "c" = "blue")))
image

如果您指定多個向量,則會有多個注釋(foobar)烟央。您還可以看到foobar全部放入單個HeatmapAnnotation()中是如何設(shè)置col . 也許現(xiàn)在您可以理解顏色列表中的名稱實際上是用來映射到注釋名稱的统诺。col中的值將用于構(gòu)建簡單注釋的圖例。

ha = HeatmapAnnotation(
    foo = 1:10, 
    bar = sample(letters[1:3], 10, replace = TRUE),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    )
)
image

NA值的顏色由na_col參數(shù)控制疑俭。

ha = HeatmapAnnotation(
    foo = c(1:4, NA, 6:10), 
    bar = c(NA, sample(letters[1:3], 9, replace = TRUE)),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    ),
    na_col = "black"
)
image

gp 主要控制網(wǎng)格邊界的圖形參數(shù)粮呢。

ha = HeatmapAnnotation(
    foo = 1:10, 
    bar = sample(letters[1:3], 10, replace = TRUE),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    ),
    gp = gpar(col = "black")
)
image

簡單注釋也可以是矩陣(數(shù)字或字符),矩陣中的所有列共享相同的顏色映射模式钞艇。注意矩陣中的列對應(yīng)于列注釋中的行啄寡。矩陣的列名稱也用作注釋名稱。

ha = HeatmapAnnotation(foo = cbind(a = runif(10), b = runif(10)))
image.png

如果矩陣沒有列名哩照,則仍然使用注解的名稱挺物,但繪制在注解的中間。

ha = HeatmapAnnotation(foo = cbind(runif(10), runif(10)))
image.png

由于簡單的注釋可以采用不同的模式(例如數(shù)字或字符)葡秒,它們可以組合為數(shù)據(jù)幀并發(fā)送到df參數(shù)姻乓。在你的項目中成像嵌溢,你可能已經(jīng)有了一個注釋表,你可以直接通過 df.

anno_df = data.frame(foo = 1:10,
    bar = sample(letters[1:3], 10, replace = TRUE))
ha = HeatmapAnnotation(df = anno_df,
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    )
)
image.png

單個注釋和數(shù)據(jù)框可以混合使用蹋岩。在以下示例中赖草,foo2由于未指定顏色,將使用隨機顏色剪个。

ha = HeatmapAnnotation(df = anno_df,
    foo2 = rnorm(10),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    )
)
image

border 控制每個注釋的邊界秧骑。

ha = HeatmapAnnotation(
    foo = cbind(1:10, 10:1),
    bar = sample(letters[1:3], 10, replace = TRUE),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    ),
    border = TRUE
)
image

簡單注釋的高度由simple_anno_size 參數(shù)控制。由于所有單個注釋具有相同的高度扣囊,因此 的值 simple_anno_size是單個unit值乎折。注意有喜歡爭論 widthheight侵歇,annotation_widthannotation_height骂澄,但它們是用來調(diào)整的完整heamtap注釋(這總是混合幾種注釋)的寬度/高度。

ha = HeatmapAnnotation(
    foo = cbind(a = 1:10, b = 10:1), 
    bar = sample(letters[1:3], 10, replace = TRUE),
    col = list(foo = col_fun,
               bar = c("a" = "red", "b" = "green", "c" = "blue")
    ),
    simple_anno_size = unit(1, "cm")
)
image

當(dāng)您有多個熱圖時惕虑,最好將所有熱圖上的簡單注釋的大小保持相同的大小坟冲。ht_opt$simple_anno_size可以設(shè)置全局控制簡單注解的大小。

3.2簡單注釋作為注釋函數(shù)

HeatmapAnnotation()通過將注釋設(shè)置為函數(shù)來支持“復(fù)雜注釋”溃蔫。annotation 函數(shù)定義了如何在熱圖中的列或行對應(yīng)的某個位置繪制圖形健提。ComplexHeatmap包中預(yù)定義了很多注釋函數(shù) 。在本章的最后伟叛,我們將介紹如何通過AnnotationFunction類構(gòu)造自己的注釋函數(shù)私痹。

對于anno_*()形式的所有注釋函數(shù),如果在HeatmapAnnotation()rowAnnotation()中指定 统刮,則不需要明確地做任何anno_*()事情來判斷它是應(yīng)該繪制在行上還是列上紊遵。anno_*()將會自動檢測是行注釋環(huán)境還是列注釋環(huán)境。

上一節(jié)中的簡單注解是由anno_simple()注解函數(shù)內(nèi)部構(gòu)造的 侥蒙。直接使用anno_simple() 不會自動為最終繪圖生成圖例癞蚕,但是,它可以為更多的注釋圖形提供更大的靈活性(注意在第5章 我們將展示辉哥,雖然anno_simple()不能自動生成圖例,但可以控制圖例并添加到最終繪圖中手動)攒射。

對于上一節(jié)中的示例:

# code only for demonstration
ha = HeatmapAnnotation(foo = 1:10)

實際上等同于:

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_simple(1:10))

anno_simple()制作類似熱圖的注釋(或簡單的注釋)醋旦。基本上如果用戶只做類似熱圖的注釋会放,他們不需要直接使用anno_simple()饲齐,但是這個功能允許在注釋網(wǎng)格上添加更多符號。

anno_simple()允許在注釋網(wǎng)格頂部添加“點”或單字母符號咧最。pch捂人,pt_gppt_size控制點的設(shè)置御雕。pch的值可以是具有可能NA值的向量。

ha = HeatmapAnnotation(foo = anno_simple(1:10, pch = 1, 
    pt_gp = gpar(col = "red"), pt_size = unit(1:10, "mm")))
image

設(shè)置pch為向量:

ha = HeatmapAnnotation(foo = anno_simple(1:10, pch = 1:10))
image

設(shè)置pch為字母向量:

ha = HeatmapAnnotation(foo = anno_simple(1:10, 
    pch = sample(letters[1:3], 10, replace = TRUE)))
image

設(shè)置pch為帶有NA值的向量(pch 值為NA不繪制任何內(nèi)容):

ha = HeatmapAnnotation(foo = anno_simple(1:10, pch = c(1:4, NA, 6:8, NA, 10, 11)))
image

如果 anno_simple()的值是矩陣滥搭,pch也可以使用酸纲。 pch的長度應(yīng)該與矩陣的行數(shù)或列數(shù)甚至矩陣的長度相同(矩陣的長度是矩陣中所有數(shù)據(jù)點的長度)。

pch的長度對應(yīng)矩陣的列:

ha = HeatmapAnnotation(foo = anno_simple(cbind(1:10, 10:1), pch = 1:2))
image

pch對應(yīng)于矩陣行的長度:

ha = HeatmapAnnotation(foo = anno_simple(cbind(1:10, 10:1), pch = 1:10))
image.png

pch 是一個矩陣:

pch = matrix(1:20, nc = 2)
pch[sample(length(pch), 10)] = NA
ha = HeatmapAnnotation(foo = anno_simple(cbind(1:10, 10:1), pch = pch))
image

到現(xiàn)在為止瑟匆,您可能想知道如何設(shè)置已添加到簡單注釋中的符號的圖例闽坡。在這里,我們將僅向您展示一個簡單的示例愁溜,在下面的例子中疾嗅,我們假設(shè)簡單的注釋是一種 p 值,我們將 p 值小于 0.01 的添加* 冕象。

set.seed(123)
pvalue = 10^-runif(10, min = 0, max = 3)
is_sig = pvalue < 0.01
pch = rep("*", 10)
pch[!is_sig] = NA
# color mapping for -log10(pvalue)
pvalue_col_fun = colorRamp2(c(0, 2, 3), c("green", "white", "red")) 
ha = HeatmapAnnotation(
    pvalue = anno_simple(-log10(pvalue), col = pvalue_col_fun, pch = pch),
    annotation_name_side = "left")
ht = Heatmap(matrix(rnorm(100), 10), name = "mat", top_annotation = ha)
# now we generate two legends, one for the p-value
# see how we define the legend for pvalue
lgd_pvalue = Legend(title = "p-value", col_fun = pvalue_col_fun, at = c(0, 1, 2, 3), 
    labels = c("1", "0.1", "0.01", "0.001"))
# and one for the significant p-values
lgd_sig = Legend(pch = "*", type = "points", labels = "< 0.01")
# these two self-defined legends are added to the plot by `annotation_legend_list`
draw(ht, annotation_legend_list = list(lgd_pvalue, lgd_sig))
image

anno_simple()的高度可以通過height參數(shù)或 simple_anno_size內(nèi)部控制代承。simple_anno_size控制單行注釋的大小和height/width控制簡單注釋的總高度/寬度。如果設(shè)置了height/ width渐扮, simple_anno_size則被忽略论悴。

ha = HeatmapAnnotation(foo = anno_simple(1:10, height = unit(2, "cm")))
image
ha = HeatmapAnnotation(foo = anno_simple(cbind(1:10, 10:1), 
    simple_anno_size = unit(2, "cm")))
image

對于我們后面介紹的所有注釋函數(shù),單個注釋的高度或?qū)挾榷紤?yīng)該在anno_*() 函數(shù)內(nèi)部進(jìn)行設(shè)置席爽。

# code only for demonstration
anno_*(..., width = ...)
anno_*(..., height = ...)

同樣意荤,widthheight只锻,annotation_widthannotation_height 在參數(shù)HeatmapAnnotation()被用于調(diào)整多個注釋的大小玖像。

3.3 空注釋

anno_empty()是一個不繪制任何內(nèi)容的占位符。以后可以通過decorate_annotation()功能添加用戶定義的圖形齐饮。

ha = HeatmapAnnotation(foo = anno_empty(border = TRUE))
image

在后續(xù)章節(jié)中將介紹裝飾函數(shù)的使用捐寥,但在這里我們舉一個簡單的例子。在基因表達(dá)表達(dá)分析中,有些情況下我們將熱圖分成幾組印衔,我們希望突出顯示每組中的一些關(guān)鍵基因梭纹。在這種情況下,我們只需將基因名稱添加到熱圖的右側(cè)乡洼,而不將它們與相應(yīng)的行對齊。(anno_mark()可以將標(biāo)簽正確地與其對應(yīng)的行對齊匕坯,但在在這里顯示的示例中束昵,這不是必需的)。

在以下示例中葛峻,由于行被拆分為四個切片锹雏,因此空注釋也被拆分為四個切片∈踅保基本上我們所做的是在每個空的注釋切片中礁遵,我們添加一個彩色段和文本轻绞。

random_text = function(n) {
    sapply(1:n, function(i) {
        paste0(sample(letters, sample(4:10, 1)), collapse = "")
    })
}
text_list = list(
    text1 = random_text(4),
    text2 = random_text(4),
    text3 = random_text(4),
    text4 = random_text(4)
)
# note how we set the width of this empty annotation
ha = rowAnnotation(foo = anno_empty(border = FALSE, 
    width = max_text_width(unlist(text_list)) + unit(4, "mm")))
Heatmap(matrix(rnorm(1000), nrow = 100), name = "mat", row_km = 4, right_annotation = ha)
for(i in 1:4) {
    decorate_annotation("foo", slice = i, {
        grid.rect(x = 0, width = unit(2, "mm"), gp = gpar(fill = i, col = NA), just = "left")
        grid.text(paste(text_list[[i]], collapse = "\n"), x = unit(4, "mm"), just = "left")
    })
}
image

空注釋的第二個用途是添加復(fù)雜的注釋圖形,其中空注釋偽裝成虛擬繪圖區(qū)域佣耐≌可以AnnotationFunction為復(fù)雜的注釋圖形按類構(gòu)造注釋函數(shù),允許子集和拆分晰赞,但仍然可以作為次要選擇稼病,直接在空注釋內(nèi)部繪制,實現(xiàn)起來更容易掖鱼、更快(但靈活性較差然走,不允許拆分)。

下面我們將展示如何添加點注釋的“復(fù)雜版本”戏挡。唯一需要注意的是x軸(y軸如果是行注釋)上的位置應(yīng)該對應(yīng)列重新排序后的列索引芍瑞。

ha = HeatmapAnnotation(foo = anno_empty(border = TRUE, height = unit(3, "cm")))
ht = Heatmap(matrix(rnorm(100), nrow = 10), name = "mat", top_annotation = ha)
ht = draw(ht)
co = column_order(ht)
value = runif(10)
decorate_annotation("foo", {
    # value on x-axis is always 1:ncol(mat)
    x = 1:10
    # while values on y-axis is the value after column reordering
    value = value[co]
    pushViewport(viewport(xscale = c(0.5, 10.5), yscale = c(0, 1)))
    grid.lines(c(0.5, 10.5), c(0.5, 0.5), gp = gpar(lty = 2),
        default.units = "native")
    grid.points(x, value, pch = 16, size = unit(2, "mm"),
        gp = gpar(col = ifelse(value > 0.5, "red", "blue")), default.units = "native")
    grid.yaxis(at = c(0, 0.5, 1))
    popViewport()
})
image

3.4塊注釋

塊注釋更像是一個顏色塊,它在熱圖的行或列被拆分時標(biāo)識組褐墅。

Heatmap(matrix(rnorm(100), 10), name = "mat",
    top_annotation = HeatmapAnnotation(foo = anno_block(gp = gpar(fill = 2:4))),
    column_km = 3)
image

標(biāo)簽可以添加到每個塊拆檬。

Heatmap(matrix(rnorm(100), 10), 
    top_annotation = HeatmapAnnotation(foo = anno_block(gp = gpar(fill = 2:4),
        labels = c("group1", "group2", "group3"), 
        labels_gp = gpar(col = "white", fontsize = 10))),
    column_km = 3,
    left_annotation = rowAnnotation(foo = anno_block(gp = gpar(fill = 2:4),
        labels = c("group1", "group2", "group3"), 
        labels_gp = gpar(col = "white", fontsize = 10))),
    row_km = 3)
image

請注意,labels或圖形參數(shù)的長度應(yīng)與切片數(shù)具有相同的長度妥凳。

anno_block()函數(shù)為行/列切片繪制矩形竟贯,其中一個矩形僅對應(yīng)一個切片。那么逝钥,如果我們想在多個切片上繪制矩形以顯示它們屬于某些組屑那,該怎么辦,如下面的熱圖所示艘款?

set.seed(123)
mat2 = matrix(rnorm(50*50), nrow = 50)
ha = HeatmapAnnotation(foo = anno_block(gp = gpar(fill = 2:6), labels = LETTERS[1:5]))
split = rep(1:5, each = 10)
Heatmap(mat2, name = "mat2", column_split = split, top_annotation = ha, 
    column_title = NULL)
image

目前持际,很難在anno_block()中直接支持它,但仍然有解決方法哗咆。實際上蜘欲,要在多個切片上繪制矩形,我們需要知道兩件事:1. 切片在圖中的位置 2. 繪制矩形的空間晌柬。慶幸的是位置可以通過直接轉(zhuǎn)到對應(yīng)的視窗獲得姥份,并且可以通過anno_empty()函數(shù)分配空間。

在下面的代碼中年碘,我們使用anno_empty()創(chuàng)建一個空注釋:

ha = HeatmapAnnotation(
    empty = anno_empty(border = FALSE),
    foo = anno_block(gp = gpar(fill = 2:6), labels = LETTERS[1:5])
)
Heatmap(mat2, name = "mat2", column_split = split, top_annotation = ha, 
    column_title = NULL)
image

假設(shè)我們要將前三列切片作為一組殿衰,將后兩列切片作為第二組。

用于注釋的第一和第三切片的位置"empty"可以通過以下方式獲得:

seekViewport("annotation_empty_1")
loc1 = deviceLoc(x = unit(0, "npc"), y = unit(0, "npc"))
seekViewport("annotation_empty_3")
loc2 = deviceLoc(x = unit(1, "npc"), y = unit(1, "npc"))
loc2
## $x
## [1] 4.07403126835173inches
## 
## $y
## [1] 6.51051067246731inches

視圖窗口名稱"annotation_empty_1"對應(yīng)于注釋的第一個切片empty盛泡,我們?nèi)〉谝粋€“空”注釋切片的左下角和第三個切片的右上角,保存在loc1loc2變量中娱颊。

這里重要的是grid::deviceLoc()函數(shù)的使用傲诵。它直接將在某個視口中測量的位置轉(zhuǎn)換為圖形設(shè)備中的位置凯砍。

最后,我們?nèi)?code>"global"視口拴竹,因為"global" 視口的大小是圖形設(shè)備的大小悟衩,繪制矩形并添加標(biāo)簽。

seekViewport("global")
grid.rect(loc1$x, loc1$y, width = loc2$x - loc1$x, height = loc2$y - loc1$y, 
    just = c("left", "bottom"), gp = gpar(fill = "red"))
grid.text("group 1", x = (loc1$x + loc2$x)*0.5, y = (loc1$y + loc2$y)*0.5)
image

注釋的視圖窗口名稱采用固定格式栓拜,即 annotation_{annotation_name}_{slice_index}. 可以通過list_components()函數(shù)獲取完整的視口名稱集座泳。

list_components()
##  [1] "ROOT"                        "global"                     
##  [3] "global_layout"               "global-heatmaplist"         
##  [5] "main_heatmap_list"           "heatmap_mat2"               
##  [7] "mat2_heatmap_body_wrap"      "mat2_heatmap_body_1_1"      
##  [9] "mat2_heatmap_body_1_2"       "mat2_heatmap_body_1_3"      
## [11] "mat2_heatmap_body_1_4"       "mat2_heatmap_body_1_5"      
## [13] "mat2_dend_row_1"             "mat2_dend_column_1"         
## [15] "mat2_dend_column_2"          "mat2_dend_column_3"         
## [17] "mat2_dend_column_4"          "mat2_dend_column_5"         
## [19] "annotation_empty_1"          "annotation_foo_1"           
## [21] "annotation_empty_2"          "annotation_foo_2"           
## [23] "annotation_empty_3"          "annotation_foo_3"           
## [25] "annotation_empty_4"          "annotation_foo_4"           
## [27] "annotation_empty_5"          "annotation_foo_5"           
## [29] "global-heatmap_legend_right" "heatmap_legend"

如果要添加多個組級矩形,我們可以將代碼包裝成一個簡單的函數(shù)group_block_anno()

ha = HeatmapAnnotation(
    empty = anno_empty(border = FALSE, height = unit(8, "mm")),
    foo = anno_block(gp = gpar(fill = 2:6), labels = LETTERS[1:5])
)
Heatmap(mat2, name = "mat2", column_split = split, top_annotation = ha, 
    column_title = NULL)

library(GetoptLong)  # for the function qq()
group_block_anno = function(group, empty_anno, gp = gpar(), 
    label = NULL, label_gp = gpar()) {

    seekViewport(qq("annotation_@{empty_anno}_@{min(group)}"))
    loc1 = deviceLoc(x = unit(0, "npc"), y = unit(0, "npc"))
    seekViewport(qq("annotation_@{empty_anno}_@{max(group)}"))
    loc2 = deviceLoc(x = unit(1, "npc"), y = unit(1, "npc"))

    seekViewport("global")
    grid.rect(loc1$x, loc1$y, width = loc2$x - loc1$x, height = loc2$y - loc1$y, 
        just = c("left", "bottom"), gp = gp)
    if(!is.null(label)) {
        grid.text(label, x = (loc1$x + loc2$x)*0.5, y = (loc1$y + loc2$y)*0.5, gp = label_gp)
    }
}

group_block_anno(1:3, "empty", gp = gpar(fill = "red"), label = "group 1")
group_block_anno(4:5, "empty", gp = gpar(fill = "blue"), label = "group 2")
image

當(dāng)熱圖被分割時幕与,塊注釋中的每個塊都可以被認(rèn)為是一個虛擬的繪圖區(qū)域挑势。anno_block()允許一個新參數(shù)graphics,該參數(shù)接受在每個切片中繪制圖形的自定義函數(shù)啦鸣。它必須有兩個參數(shù):

  1. 當(dāng)前切片的行/列索引(我們稱之為index)潮饱,
  2. 來自 split 變量的與當(dāng)前切片相對應(yīng)的水平向量(我們稱之為level)。當(dāng) e.g row_km僅設(shè)置或row_split僅設(shè)置為一個分類變量時诫给,則level是長度為 1 的向量香拉。如果有多個分類變量用row_km和設(shè)置row_splitlevel則是一個長度與分類變量個數(shù)相同的向量中狂。

設(shè)置圖形時凫碌,將忽略 anno_block 中的所有其他圖形參數(shù)。請參閱以下示例:

col = c("1" = "red", "2" = "blue", "A" = "green", "B" = "orange")
Heatmap(matrix(rnorm(100), 10), row_km = 2, row_split = sample(c("A", "B"), 10, replace = TRUE)) + 
rowAnnotation(foo = anno_block(
    graphics = function(index, levels) {
        grid.rect(gp = gpar(fill = col[levels[2]], col = "black"))
        txt = paste(levels, collapse = ",")
        txt = paste0(txt, "\n", length(index), " rows")
        grid.text(txt, 0.5, 0.5, rot = 0,
            gp = gpar(col = col[levels[1]]))
    },
    width = unit(3, "cm")
))
image

3.5圖像標(biāo)注

圖像可以作為注釋胃榕。anno_image()支持png, svg, pdf, eps, jpeg/jpg,tiff格式的圖像盛险。它們作為注釋導(dǎo)入的方式如下:

  • pngjpeg/jpgtiff圖像由png::readPNG()勤晚、 jpeg::readJPEG()tiff::readTIFF()導(dǎo)入并由 grid::grid.raster()繪制枉层。
  • svg圖像首先由rsvg::rsvg_svg()重新格式化,然后由grImport2::readPicture()導(dǎo)入和grImport2::grid.picture()繪制赐写。
  • pdfeps圖像由grImport::PostScriptTrace()grImport::readPicture()導(dǎo)入鸟蜡,然后由 grImport::grid.picture()繪制。

以下示例的免費圖標(biāo)來自 https://github.com/Keyamoon/IcoMoon-Free挺邀。圖像路徑向量被設(shè)置為 的第一個參數(shù)anno_image()揉忘。

image_png = sample(dir("IcoMoon-Free-master/PNG/64px", full.names = TRUE), 10)
image_svg = sample(dir("IcoMoon-Free-master/SVG/", full.names = TRUE), 10)
image_eps = sample(dir("IcoMoon-Free-master/EPS/", full.names = TRUE), 10)
image_pdf = sample(dir("IcoMoon-Free-master/PDF/", full.names = TRUE), 10)

# we only draw the image annotation for PNG images, while the others are the same
ha = HeatmapAnnotation(foo = anno_image(image_png))
image

不同格式的圖像可以在輸入向量中混合使用。

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_image(c(image_png[1:3], image_svg[1:3], 
    image_eps[1:3], image_pdf[1:3])))

邊框和背景顏色(如果圖像具有透明背景)可以通過gp設(shè)置端铛。

ha = HeatmapAnnotation(foo = anno_image(image_png, 
    gp = gpar(fill = 1:10, col = "black")))
image

border 控制整個邊界的注釋泣矛。

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_image(image_png, border = "red"))

圖像周圍的填充或空間由 space設(shè)置。

ha = HeatmapAnnotation(foo = anno_image(image_png, space = unit(3, "mm")))
image

如果只需要繪制部分圖像禾蚕,可以將image 向量中的其它元素設(shè)置為''NA您朽。

image_png[1:2] = ""
ha = HeatmapAnnotation(foo = anno_image(image_png))
image

3.6 點注釋

點注釋anno_points()為實現(xiàn)顯示數(shù)據(jù)點在列表中的分布。數(shù)據(jù)點對象x可以是單個向量或矩陣换淆。如果它是一個矩陣哗总,圖形屬性設(shè)置(例如pch几颜,sizegp)可以關(guān)聯(lián)到矩陣的列。再次注意讯屈,如果x是矩陣蛋哭,則行x 對應(yīng)于熱圖矩陣中的列。

ha = HeatmapAnnotation(foo = anno_points(runif(10)))
image
ha = HeatmapAnnotation(foo = anno_points(matrix(runif(20), nc = 2), 
    pch = 1:2, gp = gpar(col = 2:3)))
image

ylim控制“y軸”或“數(shù)據(jù)軸”上的范圍(如果是行注釋涮母,則數(shù)據(jù)軸為水平)谆趾,extend控制數(shù)據(jù)軸方向上的擴展空間。axis控制是否顯示軸并控制軸 axis_param的設(shè)置叛本。軸的默認(rèn)設(shè)置為:

default_axis_param("column")
## $at
## NULL
## 
## $labels
## NULL
## 
## $labels_rot
## [1] 0
## 
## $gp
## $fontsize
## [1] 8
## 
## 
## $side
## [1] "left"
## 
## $facing
## [1] "outside"
## 
## $direction
## [1] "normal"

你可以覆蓋其中的一些:

ha = HeatmapAnnotation(foo = anno_points(runif(10), ylim = c(0, 1),
    axis_param = list(
        side = "right",
        at = c(0, 0.5, 1), 
        labels = c("zero", "half", "one")
    ))
)
image

控制軸標(biāo)簽的旋轉(zhuǎn)可能對你有用沪蓬。

ha = rowAnnotation(foo = anno_points(runif(10), ylim = c(0, 1),
    width = unit(2, "cm"),
    axis_param = list(
        side = "bottom",
        at = c(0, 0.5, 1), 
        labels = c("zero", "half", "one"),
        labels_rot = 45
    ))
)
image

軸的配置與其他具有軸的注釋功能相同。

點注釋的默認(rèn)大小為 5mm炮赦。它可以由height/width中的參數(shù)控制 anno_points()怜跑。

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_points(runif(10), height = unit(2, "cm")))

3.7 線注釋

anno_lines()通過段列表連接數(shù)據(jù)點。與 anno_points()類似吠勘,數(shù)據(jù)變量可以是數(shù)值向量:

ha = HeatmapAnnotation(foo = anno_lines(runif(10)))
image

或矩陣:

ha = HeatmapAnnotation(foo = anno_lines(cbind(c(1:5, 1:5), c(5:1, 5:1)), 
    gp = gpar(col = 2:3), add_points = TRUE, pt_gp = gpar(col = 5:6), pch = c(1, 16)))
image

如上所示性芬,可以通過設(shè)置將點添加到線中add_points = TRUE

通過設(shè)置smooth = TRUE可以添加平滑線(by loess())而不是原始線剧防,但應(yīng)謹(jǐn)慎使用植锉,因為熱圖中列的順序用作擬合的“x值”,并且僅當(dāng)您認(rèn)為擬合反對重新排序的順序是有道理的峭拘。

當(dāng)輸入數(shù)據(jù)變量是對每一列單獨執(zhí)行平滑的矩陣時俊庇,平滑也有效。

如果smoothTRUE鸡挠,add_points則默認(rèn)設(shè)置為TRUE辉饱。

ha = HeatmapAnnotation(foo = anno_lines(runif(10), smooth = TRUE))
image

線注釋的默認(rèn)大小為 5 毫米。它可以由height/ 中的width參數(shù)控制 anno_lines()拣展。

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_lines(runif(10), height = unit(2, "cm")))

3.8條形圖標(biāo)注

數(shù)據(jù)點可以表示為條形圖彭沼。 anno_barplot()的一些參數(shù):如ylimaxis备埃,axis_paramanno_points()是一樣的姓惑。

ha = HeatmapAnnotation(foo = anno_barplot(1:10))
image

條行圖的寬度由 bar_width控制。它是熱圖中單元格寬度的相對值按脚。

ha = HeatmapAnnotation(foo = anno_barplot(1:10, bar_width = 1))
image

圖形參數(shù)由gp控制于毙。

ha = HeatmapAnnotation(foo = anno_barplot(1:10, gp = gpar(fill = 1:10)))
image

您可以通過baseline選擇條形的基線。

ha = HeatmapAnnotation(foo = anno_barplot(seq(-5, 5), baseline = "min"))
image
ha = HeatmapAnnotation(foo = anno_barplot(seq(-5, 5), baseline = 0))
image

如果輸入值是一個矩陣辅搬,它將是堆疊的條形圖唯沮。

ha = HeatmapAnnotation(foo = anno_barplot(matrix(nc = 2, c(1:10, 10:1))))
image

gp參數(shù)的長度可以是矩陣中的列數(shù):

ha = HeatmapAnnotation(foo = anno_barplot(cbind(1:10, 10:1), 
    gp = gpar(fill = 2:3, col = 2:3)))
image

條形圖注釋的默認(rèn)大小為 5 毫米。它可以由height/width中的參數(shù)控制 anno_barplot()

# code only for demonstration
ha = HeatmapAnnotation(foo = anno_barplot(runif(10), height = unit(2, "cm")))

以下示例顯示了可視化比例矩陣的條形圖注釋(行總和為 1)介蛉。

m = matrix(runif(4*10), nc = 4)
m = t(apply(m, 1, function(x) x/sum(x)))
ha = HeatmapAnnotation(foo = anno_barplot(m, gp = gpar(fill = 2:5), 
    bar_width = 1, height = unit(6, "cm")))
image

軸的方向可以反轉(zhuǎn)夯缺,這在注釋放在熱圖左側(cè)時很有用。

ha_list = rowAnnotation(axis_reverse = anno_barplot(m, gp = gpar(fill = 2:5), 
    axis_param = list(direction = "reverse"), 
    bar_width = 1, width = unit(4, "cm"))) +
rowAnnotation(axis_normal = anno_barplot(m, gp = gpar(fill = 2:5), 
    bar_width = 1, width = unit(4, "cm")))
draw(ha_list, ht_gap = unit(4, "mm"))
image

direction = "reverse" 也適用于其他具有軸的注釋函數(shù)甘耿,但它常用于條形圖注釋。

add_numbers可以將參數(shù)設(shè)置為TRUE竿滨,以便在條形頂部繪制與條形關(guān)聯(lián)的數(shù)字佳恬。對于列注釋,文本默認(rèn)旋轉(zhuǎn) 45 度于游。

ha = HeatmapAnnotation(foo = anno_barplot(1:10, add_numbers = TRUE, 
    height = unit(1, "cm")))
image

3.9箱線圖注釋

Boxplot注解以及后面介紹的注解函數(shù)更適合小矩陣毁葱。不適合就有多列矩陣的列注釋。

對于anno_boxplot()贰剥,輸入數(shù)據(jù)變量應(yīng)該是矩陣或列表倾剿。如果 x是矩陣,如果是列注釋蚌成,則箱線圖的統(tǒng)計量按列計算前痘,如果是行注釋,則按行計算担忧。

set.seed(12345)
m = matrix(rnorm(100), 10)
ha = HeatmapAnnotation(foo = anno_boxplot(m, height = unit(4, "cm")))
image

圖形參數(shù)由gp控制芹缔。

ha = HeatmapAnnotation(foo = anno_boxplot(m, height = unit(4, "cm"), 
    gp = gpar(fill = 1:10)))
image

框的寬度由box_width控制。outline控制是否顯示離群點瓶盛。

ha = HeatmapAnnotation(foo = anno_boxplot(m, height = unit(4, "cm"), 
    box_width = 0.9, outline = FALSE))
image

anno_boxplot()只為一行繪制一個箱線圖最欠。多個箱線圖注釋演示了如何定義為單行繪制多個箱線圖的注釋函數(shù),單個箱線圖演示如何為一組行繪制單個箱線圖惩猫。

3.10直方圖標(biāo)注

作為直方圖的注釋更適合作為行注釋芝硬。數(shù)據(jù)變量的設(shè)置與anno_boxplot()相同,可以是矩陣或列表轧房。

anno_boxplot()類似拌阴,輸入數(shù)據(jù)變量應(yīng)該是矩陣或列表。如果 x是矩陣锯厢,如果是列注釋皮官,則直方圖按列計算,如果是行注釋实辑,則直方圖按行計算捺氢。

m = matrix(rnorm(1000), nc = 100)
ha = rowAnnotation(foo = anno_histogram(m)) # apply `m` on rows
image

直方圖的中斷次數(shù)由n_breaks控制。

ha = rowAnnotation(foo = anno_histogram(m, n_breaks = 20))
image

顏色由gp控制剪撬。

ha = rowAnnotation(foo = anno_histogram(m, gp = gpar(fill = 1:10)))
image

3.11密度曲線注釋

與直方圖注釋類似摄乒,anno_density()將分布顯示為擬合曲線。

ha = rowAnnotation(foo = anno_density(m))
image

可以控制密度峰值的高度,使分布看起來像一個“joyplot”馍佑。

ha = rowAnnotation(foo = anno_density(m, joyplot_scale = 2, 
    gp = gpar(fill = "#CCCCCC80")))
image

或者將分布可視化為小提琴圖斋否。

ha = rowAnnotation(foo = anno_density(m, type = "violin", 
    gp = gpar(fill = 1:10)))
image

當(dāng)輸入變量中有太多行時,正常密度峰值的空間可能太小拭荤。在這種情況下茵臭,我們可以通過熱圖可視化分布。

m2 = matrix(rnorm(50*10), nrow = 50)
ha = rowAnnotation(foo = anno_density(m2, type = "heatmap", width = unit(6, "cm")))
image

熱圖分布的顏色模式由heatmap_colors控制舅世。

ha = rowAnnotation(foo = anno_density(m2, type = "heatmap", width = unit(6, "cm"), 
    heatmap_colors = c("white", "orange")))
image

ComplexHeatmap包中旦委,有一個densityHeatmap()函數(shù)可以將分布可視化為熱圖。將在密度熱圖介紹 雏亚。

3.12 Joyplot注釋

anno_joyplot()特定于所謂的 Joyplot ( http://blog.revolutionanalytics.com/2017/07/joyplots.html )缨硝。輸入數(shù)據(jù)應(yīng)該是矩陣或列表。

anno_joyplot()如果輸入是矩陣罢低,則注釋始終應(yīng)用于列查辩。因為joyplot可視化了平行分布,矩陣不是必需的格式网持,列表已經(jīng)足夠了宜岛,如果你不確定如何設(shè)置為矩陣,只需將其轉(zhuǎn)換為列表來使用它翎碑。

m = matrix(rnorm(1000), nc = 10)
lt = apply(m, 2, function(x) data.frame(density(x)[c("x", "y")]))
ha = rowAnnotation(foo = anno_joyplot(lt, width = unit(4, "cm"), 
    gp = gpar(fill = 1:10), transparency = 0.75))
image

或者只顯示線條(scale參數(shù)控制曲線的相對高度)谬返。

m = matrix(rnorm(5000), nc = 50)
lt = apply(m, 2, function(x) data.frame(density(x)[c("x", "y")]))
ha = rowAnnotation(foo = anno_joyplot(lt, width = unit(4, "cm"), gp = gpar(fill = NA), 
    scale = 4))
image

輸入變量的格式很特殊。它可以是以下兩個之一:

  1. 一個矩陣(記住anno_joyplot()總是應(yīng)用于矩陣的列)日杈,其中 x 坐標(biāo)1:nrow(matrix)對應(yīng)于矩陣中的每一列對應(yīng)于圖中的一個分布遣铝。
  2. 一個數(shù)據(jù)框列表,其中每個數(shù)據(jù)框有兩列對應(yīng)于 x 坐標(biāo)和 y 坐標(biāo)莉擒。

3.13地平線圖標(biāo)注

水平線圖 作為注釋只能添加為行注釋酿炸。輸入變量的格式與上面介紹anno_horizon()的相同anno_joyplot()

地平線圖注釋的默認(rèn)樣式為:

lt = lapply(1:20, function(x) cumprod(1 + runif(1000, -x/100, x/100)) - 1)
ha = rowAnnotation(foo = anno_horizon(lt))
image

每個軌道中的值通過 歸一化x/max(abs(x))涨冀。

對于正值和負(fù)值的顏色是由gpar()pos_fillneg_fill控制填硕。

ha = rowAnnotation(foo = anno_horizon(lt, 
    gp = gpar(pos_fill = "orange", neg_fill = "darkgreen")))
image

pos_fillneg_fill可以作為向量分配。

ha = rowAnnotation(foo = anno_horizon(lt, 
    gp = gpar(pos_fill = rep(c("orange", "red"), each = 10),
              neg_fill = rep(c("darkgreen", "blue"), each = 10))))
image

負(fù)值的峰值是從底部還是從頂部開始鹿鳖。

ha = rowAnnotation(foo = anno_horizon(lt, negative_from_top = TRUE))
image

每兩個相鄰圖表之間的空間扁眯。

ha = rowAnnotation(foo = anno_horizon(lt, gap = unit(1, "mm")))
image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市翅帜,隨后出現(xiàn)的幾起案子姻檀,更是在濱河造成了極大的恐慌,老刑警劉巖涝滴,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绣版,死亡現(xiàn)場離奇詭異胶台,居然都是意外死亡,警方通過查閱死者的電腦和手機杂抽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門诈唬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缩麸,你說我怎么就攤上這事铸磅。” “怎么了杭朱?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵愚屁,是天一觀的道長。 經(jīng)常有香客問我痕檬,道長,這世上最難降的妖魔是什么送浊? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任梦谜,我火速辦了婚禮,結(jié)果婚禮上袭景,老公的妹妹穿的比我還像新娘唁桩。我一直安慰自己,他們只是感情好耸棒,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布荒澡。 她就那樣靜靜地躺著,像睡著了一般与殃。 火紅的嫁衣襯著肌膚如雪单山。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天幅疼,我揣著相機與錄音米奸,去河邊找鬼。 笑死爽篷,一個胖子當(dāng)著我的面吹牛悴晰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逐工,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼铡溪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了泪喊?” 一聲冷哼從身側(cè)響起棕硫,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窘俺,沒想到半個月后饲帅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體复凳,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年灶泵,在試婚紗的時候發(fā)現(xiàn)自己被綠了育八。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡赦邻,死狀恐怖髓棋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情惶洲,我是刑警寧澤按声,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站恬吕,受9級特大地震影響签则,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铐料,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一渐裂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钠惩,春花似錦柒凉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至愧沟,卻和暖如春蔬咬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背沐寺。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工计盒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芽丹。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓北启,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拔第。 傳聞我的和親對象是個殘疾皇子咕村,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容