ComplexHeatmap复杂热图绘制学习——3.热图注释(一)

第 3 章 热图注释

热图注释是热图的重要组成部分,它显示与热图中的行或列相关联的附加信息。 ComplexHeatmap包为设置注释和定义新的注释图形提供了非常灵活的支持。注释可以放在热图的四个侧面,由top_annotationbottom_annotationleft_annotationright_annotation参数组成。

接下来我们将对不同第注释函数anno_*()进行说明,如空注释anno_empty()、块注释anno_block()、图像注释anno_image()、点注释anno_points()、线注释anno_lines()、条形图注释anno_barplot()、箱线图注释anno_boxplot()、直方图注释anno_histogram()、密度注释anno_density()等注释方法。

四个参数的值应该在HeatmapAnnotation类中并且由HeatmapAnnotation()函数构造,如果是行注释则由rowAnnotation()函数构造。(rowAnnotation()只是一个与HeatmapAnnotation(..., which = "row")相同的辅助函数) ,热图注释的简单用法如下。

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

将热图注释指定为底部注释和左侧注释。

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

在上面的例子中,column_harow_ha都有两个注释,其中 foo1foo2是数字向量,bar1bar2是条形图。类似向量的注解在这里称为“简单注释”,条形图注解称为“复杂注释”。您已经可以看到注释必须定义为名称=值对(例如 foo = ...)。

热图注释也可以独立于热图。它们可以通过+(水平连接)或%v%(垂直连接)到热图列表。

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

HeatmapAnnotation()返回一个HeatmapAnnotation类对象。对象通常由几个注释组成。如以下部分,首先介绍单个注释的设置,然后展示如何将它们组合在一起。

可以看到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_annotationleft_annotationright_annotation讨论对象。

列注释和行注释的设置基本相同。如果没有什么特别的,我们只以列注释作为示例。如果您想尝试一行注释,只需添加which = "row"HeatmapAnnotation()或直接切换到rowAnnotation()功能。

3.1简单注释

所谓的“简单注释”是最常用的注释样式,它是类似热图或类似网格的图形,其中使用颜色映射到注释值。要生成一个简单的注释,您只需简单地将一个特定的名称注释向量放入HeatmapAnnotation()中。

ha = HeatmapAnnotation(foo = 1:10)
image

离散型数据注释:

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

除了HeatmapAnnotation(),您可以使用任何字符串作为注释名称。

如果未指定颜色,则随机生成颜色。col设置注释的颜色,col需要设置命名列表。

对于连续值注释,颜色映射应该是由 circlize::colorRamp2()生成的颜色映射函数。

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

对于离散注释,颜色应该是命名向量,其中名称对应于注释中的级别。

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

如果您指定多个向量,则会有多个注释(foobar)。您还可以看到foobar全部放入单个HeatmapAnnotation()中是如何设置col . 也许现在您可以理解颜色列表中的名称实际上是用来映射到注释名称的。col中的值将用于构建简单注释的图例。

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参数控制。

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 主要控制网格边界的图形参数。

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

简单注释也可以是矩阵(数字或字符),矩阵中的所有列共享相同的颜色映射模式。注意矩阵中的列对应于列注释中的行。矩阵的列名称也用作注释名称。

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

如果矩阵没有列名,则仍然使用注解的名称,但绘制在注解的中间。

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

由于简单的注释可以采用不同的模式(例如数字或字符),它们可以组合为数据帧并发送到df参数。在你的项目中成像,你可能已经有了一个注释表,你可以直接通过 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

单个注释和数据框可以混合使用。在以下示例中,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 参数控制。由于所有单个注释具有相同的高度,因此 的值 simple_anno_size是单个unit值。注意有喜欢争论 widthheightannotation_widthannotation_height,但它们是用来调整的完整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

当您有多个热图时,最好将所有热图上的简单注释的大小保持相同的大小。ht_opt$simple_anno_size可以设置全局控制简单注解的大小。

3.2简单注释作为注释函数

HeatmapAnnotation()通过将注释设置为函数来支持“复杂注释”。annotation 函数定义了如何在热图中的列或行对应的某个位置绘制图形。ComplexHeatmap包中预定义了很多注释函数 。在本章的最后,我们将介绍如何通过AnnotationFunction类构造自己的注释函数。

对于anno_*()形式的所有注释函数,如果在HeatmapAnnotation()rowAnnotation()中指定 ,则不需要明确地做任何anno_*()事情来判断它是应该绘制在行上还是列上。anno_*()将会自动检测是行注释环境还是列注释环境。

上一节中的简单注解是由anno_simple()注解函数内部构造的 。直接使用anno_simple() 不会自动为最终绘图生成图例,但是,它可以为更多的注释图形提供更大的灵活性(注意在第5章 我们将展示,虽然anno_simple()不能自动生成图例,但可以控制图例并添加到最终绘图中手动)。

对于上一节中的示例:

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

实际上等同于:

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

anno_simple()制作类似热图的注释(或简单的注释)。基本上如果用户只做类似热图的注释,他们不需要直接使用anno_simple(),但是这个功能允许在注释网格上添加更多符号。

anno_simple()允许在注释网格顶部添加“点”或单字母符号。pchpt_gppt_size控制点的设置。pch的值可以是具有可能NA值的向量。

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

设置pch为向量:

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

设置pch为字母向量:

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

设置pch为带有NA值的向量(pch 值为NA不绘制任何内容):

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

如果 anno_simple()的值是矩阵,pch也可以使用。 pch的长度应该与矩阵的行数或列数甚至矩阵的长度相同(矩阵的长度是矩阵中所有数据点的长度)。

pch的长度对应矩阵的列:

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

pch对应于矩阵行的长度:

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

到现在为止,您可能想知道如何设置已添加到简单注释中的符号的图例。在这里,我们将仅向您展示一个简单的示例,在下面的例子中,我们假设简单的注释是一种 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参数或 simple_anno_size内部控制。simple_anno_size控制单行注释的大小和height/width控制简单注释的总高度/宽度。如果设置了height/ widthsimple_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

对于我们后面介绍的所有注释函数,单个注释的高度或宽度都应该在anno_*() 函数内部进行设置。

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

同样,widthheightannotation_widthannotation_height 在参数HeatmapAnnotation()被用于调整多个注释的大小。

3.3 空注释

anno_empty()是一个不绘制任何内容的占位符。以后可以通过decorate_annotation()功能添加用户定义的图形。

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

在后续章节中将介绍装饰函数的使用,但在这里我们举一个简单的例子。在基因表达表达分析中,有些情况下我们将热图分成几组,我们希望突出显示每组中的一些关键基因。在这种情况下,我们只需将基因名称添加到热图的右侧,而不将它们与相应的行对齐。(anno_mark()可以将标签正确地与其对应的行对齐,但在在这里显示的示例中,这不是必需的)。

在以下示例中,由于行被拆分为四个切片,因此空注释也被拆分为四个切片。基本上我们所做的是在每个空的注释切片中,我们添加一个彩色段和文本。

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

空注释的第二个用途是添加复杂的注释图形,其中空注释伪装成虚拟绘图区域。可以AnnotationFunction为复杂的注释图形按类构造注释函数,允许子集和拆分,但仍然可以作为次要选择,直接在空注释内部绘制,实现起来更容易、更快(但灵活性较差,不允许拆分)。

下面我们将展示如何添加点注释的“复杂版本”。唯一需要注意的是x轴(y轴如果是行注释)上的位置应该对应列重新排序后的列索引。

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块注释

块注释更像是一个颜色块,它在热图的行或列被拆分时标识组。

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

标签可以添加到每个块。

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或图形参数的长度应与切片数具有相同的长度。

anno_block()函数为行/列切片绘制矩形,其中一个矩形仅对应一个切片。那么,如果我们想在多个切片上绘制矩形以显示它们属于某些组,该怎么办,如下面的热图所示?

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. 绘制矩形的空间。庆幸的是位置可以通过直接转到对应的视窗获得,并且可以通过anno_empty()函数分配空间。

在下面的代码中,我们使用anno_empty()创建一个空注释:

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

假设我们要将前三列切片作为一组,将后两列切片作为第二组。

用于注释的第一和第三切片的位置"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"对应于注释的第一个切片empty,我们取第一个“空”注释切片的左下角和第三个切片的右上角,保存在loc1loc2变量中。

这里重要的是grid::deviceLoc()函数的使用。它直接将在某个视口中测量的位置转换为图形设备中的位置。

最后,我们去"global"视口,因为"global" 视口的大小是图形设备的大小,绘制矩形并添加标签。

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()函数获取完整的视口名称集。

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"

如果要添加多个组级矩形,我们可以将代码包装成一个简单的函数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

当热图被分割时,块注释中的每个块都可以被认为是一个虚拟的绘图区域。anno_block()允许一个新参数graphics,该参数接受在每个切片中绘制图形的自定义函数。它必须有两个参数:

  1. 当前切片的行/列索引(我们称之为index),
  2. 来自 split 变量的与当前切片相对应的水平向量(我们称之为level)。当 e.g row_km仅设置或row_split仅设置为一个分类变量时,则level是长度为 1 的向量。如果有多个分类变量用row_km和设置row_splitlevel则是一个长度与分类变量个数相同的向量。

设置图形时,将忽略 anno_block 中的所有其他图形参数。请参阅以下示例:

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图像标注

图像可以作为注释。anno_image()支持png, svg, pdf, eps, jpeg/jpg,tiff格式的图像。它们作为注释导入的方式如下:

  • pngjpeg/jpgtiff图像由png::readPNG()jpeg::readJPEG()tiff::readTIFF()导入并由 grid::grid.raster()绘制。
  • svg图像首先由rsvg::rsvg_svg()重新格式化,然后由grImport2::readPicture()导入和grImport2::grid.picture()绘制。
  • pdfeps图像由grImport::PostScriptTrace()grImport::readPicture()导入,然后由 grImport::grid.picture()绘制。

以下示例的免费图标来自 https://github.com/Keyamoon/IcoMoon-Free。图像路径向量被设置为 的第一个参数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设置。

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设置。

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

如果只需要绘制部分图像,可以将image 向量中的其它元素设置为''NA

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

3.6 点注释

点注释anno_points()为实现显示数据点在列表中的分布。数据点对象x可以是单个向量或矩阵。如果它是一个矩阵,图形属性设置(例如pchsizegp)可以关联到矩阵的列。再次注意,如果x是矩阵,则行x 对应于热图矩阵中的列。

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轴”或“数据轴”上的范围(如果是行注释,则数据轴为水平),extend控制数据轴方向上的扩展空间。axis控制是否显示轴并控制轴 axis_param的设置。轴的默认设置为:

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

控制轴标签的旋转可能对你有用。

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

轴的配置与其他具有轴的注释功能相同。

点注释的默认大小为 5mm。它可以由height/width中的参数控制 anno_points()

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

3.7 线注释

anno_lines()通过段列表连接数据点。与 anno_points()类似,数据变量可以是数值向量:

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

如上所示,可以通过设置将点添加到线中add_points = TRUE

通过设置smooth = TRUE可以添加平滑线(by loess())而不是原始线,但应谨慎使用,因为热图中列的顺序用作拟合的“x值”,并且仅当您认为拟合反对重新排序的顺序是有道理的。

当输入数据变量是对每一列单独执行平滑的矩阵时,平滑也有效。

如果smoothTRUEadd_points则默认设置为TRUE

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

线注释的默认大小为 5 毫米。它可以由height/ 中的width参数控制 anno_lines()

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

3.8条形图标注

数据点可以表示为条形图。 anno_barplot()的一些参数:如ylimaxisaxis_paramanno_points()是一样的。

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

条行图的宽度由 bar_width控制。它是热图中单元格宽度的相对值。

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

图形参数由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参数的长度可以是矩阵中的列数:

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

条形图注释的默认大小为 5 毫米。它可以由height/width中的参数控制 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

轴的方向可以反转,这在注释放在热图左侧时很有用。

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" 也适用于其他具有轴的注释函数,但它常用于条形图注释。

add_numbers可以将参数设置为TRUE,以便在条形顶部绘制与条形关联的数字。对于列注释,文本默认旋转 45 度。

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

3.9箱线图注释

Boxplot注解以及后面介绍的注解函数更适合小矩阵。不适合就有多列矩阵的列注释。

对于anno_boxplot(),输入数据变量应该是矩阵或列表。如果 x是矩阵,如果是列注释,则箱线图的统计量按列计算,如果是行注释,则按行计算。

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

图形参数由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()只为一行绘制一个箱线图。多个箱线图注释演示了如何定义为单行绘制多个箱线图的注释函数,单个箱线图演示如何为一组行绘制单个箱线图。

3.10直方图标注

作为直方图的注释更适合作为行注释。数据变量的设置与anno_boxplot()相同,可以是矩阵或列表。

anno_boxplot()类似,输入数据变量应该是矩阵或列表。如果 x是矩阵,如果是列注释,则直方图按列计算,如果是行注释,则直方图按行计算。

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

直方图的中断次数由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

当输入变量中有太多行时,正常密度峰值的空间可能太小。在这种情况下,我们可以通过热图可视化分布。

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()函数可以将分布可视化为热图。将在密度热图介绍 。

3.12 Joyplot注释

anno_joyplot()特定于所谓的 Joyplot ( http://blog.revolutionanalytics.com/2017/07/joyplots.html )。输入数据应该是矩阵或列表。

anno_joyplot()如果输入是矩阵,则注释始终应用于列。因为joyplot可视化了平行分布,矩阵不是必需的格式,列表已经足够了,如果你不确定如何设置为矩阵,只需将其转换为列表来使用它。

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参数控制曲线的相对高度)。

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()总是应用于矩阵的列),其中 x 坐标1:nrow(matrix)对应于矩阵中的每一列对应于图中的一个分布。
  2. 一个数据框列表,其中每个数据框有两列对应于 x 坐标和 y 坐标。

3.13地平线图标注

水平线图 作为注释只能添加为行注释。输入变量的格式与上面介绍anno_horizon()的相同anno_joyplot()

地平线图注释的默认样式为:

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))

对于正值和负值的颜色是由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

负值的峰值是从底部还是从顶部开始。

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

每两个相邻图表之间的空间。

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

推荐阅读更多精彩内容