剑无锋,大巧不工
大家好,我是风。在上次最后一个图片中,我们利用注释对ComplexHeatmap绘制的热图进行了修饰和美化,那这些修饰都应该怎么进行操作呢?
ComplexHeatmap在注释方面提供了非常多的可选择性,可以在图片的上、下、左、右分别加上注释的信息,分别用top_annotation,bottom_annotation,left_annotation和right_annotation, 而其中我们还可以用另外两个函数来封装注释信息,分别是HeatmapAnnotation或rowAnnotation,为了让大家能够衔接前面的内容,这次用的数据还是前面的三次推文构建的数据。
传送门
手把手教你复现一篇CNS级别美图!附代码,建议收藏!
CNS级别的美图复现起来难不难?小白也能快速上手(附代码)(二)
我们还是构建一个跟前面推文一致的数据:
加载包
# 加载R包library(ComplexHeatmap)library(circlize)# 构建一个跟之前一样的矩阵set.seed(123)nr1 = 4; nr2 = 8; nr3 = 6; nr = nr1 + nr2 + nr3nc1 = 6; nc2 = 8; nc3 = 10; nc = nc1 + nc2 + nc3mat <- 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)] rownames(mat) = paste0("gene", seq_len(nr))colnames(mat) = paste0("Sample", seq_len(nc))head(mat)## Sample1 Sample2 Sample3 Sample4 Sample5 Sample6## gene1 0.90474160 -0.35229823 0.5016096 1.26769942 0.8251229 0.16215217## gene2 0.90882972 0.79157121 1.0726316 0.01299521 0.1391978 0.46833693## gene3 0.28074668 0.02987497 0.7052595 1.21514235 0.1747267 0.20949120## gene4 0.02729558 0.75810969 0.5333504 -0.49637424 -0.5261114 0.56724357## gene5 -0.32552445 1.03264652 1.1249573 0.66695147 0.4490584 1.04236865## gene6 0.58403269 -0.47373731 0.5452483 0.86824798 -0.1976372 -0.03565404## Sample7 Sample8 Sample9 Sample10 Sample11 Sample12## gene1 -0.2869867 0.68032622 -0.1629658 0.8254537 0.7821773 -0.49625358## gene2 1.2814948 0.38998256 -0.3473535 1.3508922 1.1183375 2.05005447## gene3 -0.6423579 -0.31395304 0.2175907 -0.2973086 0.4322058 -0.25803192## gene4 0.8127096 -0.01427338 1.0844780 0.2426662 0.8783874 1.38452112## gene5 2.6205200 0.75823530 -0.2333277 1.3439584 0.8517620 0.85980233## gene6 -0.3203530 1.05534136 0.7771690 0.4594983 0.2550648 -0.02778098## Sample13 Sample14 Sample15 Sample16 Sample17 Sample18## gene1 -0.0895258 -0.35520328 0.1072694 0.96322199 -0.39245223 -0.1878014## gene2 1.3770269 -0.77437640 0.9829664 0.23854381 -0.53589561 1.3003544## gene3 -0.5686518 -0.51321045 -0.0451598 0.82272880 -0.02251386 0.2427300## gene4 0.8376570 0.10797078 0.4520019 0.81648036 0.02650211 0.4072600## gene5 1.9986067 -0.50928769 0.7708173 -0.09421702 -1.15458444 1.2715970## gene6 -0.2112484 0.01669142 -0.3259750 0.54460361 0.89101254 0.3699738## Sample19 Sample20 Sample21 Sample22 Sample23 Sample24## gene1 1.08736320 0.7132199 -0.1853300 -0.14238650 0.6407669 1.3266288## gene2 0.14237891 0.4471643 0.4475628 -0.31251963 0.7057150 0.8120937## gene3 1.09511516 0.5852612 0.1926402 0.51278568 1.6361334 1.1339175## gene4 -0.02625664 0.9556956 0.3443201 0.07668656 1.7857291 0.5280084## gene5 0.60599022 0.8304101 -0.1902355 -0.14753574 1.0123366 0.2140750## gene6 0.81537706 1.2737905 1.8575325 0.88491126 0.5670193 0.5372756
简单注释
# 随机添加注释信息column_ha <- HeatmapAnnotation(foo1 = runif(24,10,20), bar1 = anno_barplot(runif(24,10,20)))row_ha <- rowAnnotation(foo2 = runif(18,10,20), bar2 = anno_barplot(runif(18,10,20)))Heatmap(mat, name = "mat", top_annotation = column_ha, right_annotation = row_ha)
Heatmap(mat, name = "mat", bottom_annotation = column_ha, left_annotation = row_ha)
# 在上面的代码中,column_ha和row_ha都具有两个注释,其中foo1和foo2是数字矢量注释信息,而bar1和bar2是图形注释信息,像矢量一样的注释在这里被称为“简单注释”,而图形注释被称为“复杂注释”,我们把注释信息赋予了一个特定的值,比如这里的foo1和bar1
在上面的例子中我们已经看到了数字矢量进行热图注释,并且将其称为简单注释。那么什么是简单注释呢?所谓的简单注释是最常用的注释风格,它是类似热图或网格图形的注释,颜色用于映射具体值。要生成一个简单的注释,只需将注释向量以特定的名称放在HeatmapAnnotation就可以,比如这样:
ha = HeatmapAnnotation(foo = 1:24)Heatmap(mat, name = "mat", top_annotation = ha)
ha = HeatmapAnnotation(foo = sample(c("normal","tumor"), 24, replace = TRUE))Heatmap(mat, name = "mat", top_annotation = ha)
大家不妨运行多几次上面的代码,是不是发现每次颜色都不一样?那我们可以设定我们喜欢的颜色吗?当然可以:
# 使用colorRamp2设置颜色,并添加col函数添加注释信息的颜色# 对连续型注释信息进行颜色添加col_fun = colorRamp2(c(0, 50, 100), c("navy", "white", "red"))ha1 = HeatmapAnnotation(foo = runif(24,0,100), col = list(foo = col_fun))Heatmap(mat, name = "mat", bottom_annotation = ha1)
# 对离散型注释信息进行颜色添加colours <- list(SampleType = c("normal"="navy","tumor"="red"))ha2 = HeatmapAnnotation("SampleType" = sample(c("normal","tumor"), 24, replace = TRUE), col = colours)Heatmap(mat, name = "mat", top_annotation = ha2)
# 同时放入离散型变量和连续型变量ha3 = HeatmapAnnotation( foo = runif(24,0,100), SampleType = sample(c("normal","tumor"), 24, replace = TRUE),col = list(foo = col_fun, SampleType = c("normal"="navy","tumor"="red") ))Heatmap(mat, name = "mat", top_annotation = ha3)
# 如果样本中有NA值,则使用na_col赋予颜色ha4 = HeatmapAnnotation( foo = runif(24,0,100), SampleType = c(NA,sample(c("normal","tumor"), 23, replace = TRUE)),col = list(foo = col_fun, SampleType = c("normal"="lightblue","tumor"="red") ), na_col = "black")Heatmap(mat, name = "mat", top_annotation = ha4)
# 前面学过的gp一样使用于注释信息ha5 = HeatmapAnnotation( foo = runif(24,0,100), SampleType = sample(c("normal","tumor"), 24, replace = TRUE),col = list(foo = col_fun, SampleType = c("normal"="navy","tumor"="red") ), gp = gpar(col = "orange"), annotation_width=unit(c(1, 4), "cm"), gap = unit(2, "mm"))Heatmap(mat, name = "mat", top_annotation = ha5)
# 更多时候可能我们的数据是一个数据框# 可以把自己的注释信息整理成表格然后读取进来,不限制个数clinical <-data.frame(age = runif(24,0,100),SampleType = sample(c("normal","tumor"), 24, replace = TRUE))ha6 = HeatmapAnnotation(df = clinical,col = list(foo = col_fun,SampleType = c("normal"="navy","tumor"="red")),border = TRUE,simple_anno_size = unit(1, "cm"))Heatmap(mat, name = "mat", top_annotation = ha6)
# 下面同步展示一种常见的错误注释方法,注意比较ha6和ha7clinical <- cbind(runif(24,0,100), sample(c("normal","tumor"), 24, replace = TRUE))ha7 = HeatmapAnnotation(clinical = clinical)Heatmap(mat, name = "mat", top_annotation = ha7)
OK,简单注释我们就说这么多,接下来我们继续说说用函数进行简单注释。
注释函数的简单注释
HeatmapAnnotation可以通过将注释设置为函数来支持“复杂注释”,注释函数定义如何在与热图中的列或行相对应的特定位置绘制图形。对于所有形式为anno_开头的注释函数,如果在HeatmapAnnotation或rowAnnotation中指定了注释功能,则无需对anno_进行任何映射,anno_会自动检测它是行注释环境还是列注释环境:

# 前面我们用了这样的注释信息ha = HeatmapAnnotation(foo = 1:24)# 其实完整的写法应该是这样ha = HeatmapAnnotation(foo = anno_simple(1:24))# anno_simple进行类似于热图的注释(或简单注释),这个函数一般用来在注释网格上添加更多符号,比如我们常见的打×或者▲等等ha8 = HeatmapAnnotation(foo = anno_simple(1:24, pch = 1:24))Heatmap(mat, name = "mat", bottom_annotation = ha8)
# 或者自定义pch的值ha9 = HeatmapAnnotation(foo = anno_simple(1:24, pt_gp = gpar(col = "blue"), pch = sample(c("N","T"), 24, replace = TRUE)))Heatmap(mat, name = "mat", bottom_annotation = ha9)
# 如果含有NA,也可以留空白ha10 = HeatmapAnnotation(foo = anno_simple(1:24, pch = c(1:8, NA,NA,NA, 12:18, NA, 20:24)))Heatmap(mat, name = "mat", bottom_annotation = ha10)
# anno simple的对象也可以是一个矩阵ha11 = HeatmapAnnotation(foo = anno_simple(cbind(1:24, 24:1), pch = 1:2))Heatmap(mat, name = "mat", bottom_annotation = ha11)
ha12 = HeatmapAnnotation(foo = anno_simple(cbind(1:24, 24:1), pch = 1:24))Heatmap(mat, name = "mat", bottom_annotation = ha12)
# 对比上面ha11和ha12我们会发现anno函数自动检测了添加的图形是匹配了行还是列# 如果matrix中有NA值,一样可以进行修饰pch = matrix(1:48, nc = 2)pch[sample(length(pch), 10)] = NAha13 = HeatmapAnnotation(foo = anno_simple(cbind(1:24, 24:1), pch = pch))Heatmap(mat, name = "mat", bottom_annotation = ha13)

# 我们可以先计算p值,然后对p < 0.05 的结果打上* set.seed(123)pvalue = round(10^-runif(24, min = 0, max = 3),3) # 计算p值is_sig = pvalue < 0.05 # 判断p<0.05pch = rep("*", 24) # 给24个对象都打上星号pch[!is_sig] = NA # 将不满足p<0.05的结果变换成NA# 打上颜色pvalue_col_fun = colorRamp2(c(0, 2, 3), c("navy", "white", "red")) ha = HeatmapAnnotation( pvalue = anno_simple(-log10(pvalue), col = pvalue_col_fun, pch = pch), annotation_name_side = "left")ht <- Heatmap(mat, name = "mat", top_annotation = ha)draw(ht)
# 对p值的图例进行定义lgd_pvalue = Legend(title = "p-value", col = pvalue_col_fun, at = c(0, 1, 2, 3), labels = c("1", "0.1", "0.05", "0.01"))# 对<0.01的p值进行定义lgd_sig = Legend(pch = "*", type = "points", labels = "< 0.05")# 添加两个自定义的图例draw(ht, annotation_legend_list = list(lgd_pvalue, lgd_sig))
好了,今天的内容看似简单,其实组合排列花样很多,正是应了那句话“重剑无锋,大巧不工”。今天我们先到这,下回我们开始复杂的注释内容,我们下期再见吧!(●‘◡’●)
欢迎大家关注解螺旋生信频道-挑圈联靠公号~
继续阅读
阅读原文