使用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)control1control2control3treat1treat2treat3Gene......Gene......Gene......Gene......Gene......Gene......
由于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("#8ca","white","#e"))
我们限定值为-2映射为green,0映射为white,2映射为red。
在这之间的值以线性内插的方式获取到相应的值,如果值超出了[-2,2]范围
col_fun(seq(-3,3))[1]"#8CAFF""#8CAFF""#CCAFF""#FFFFFFFF""#8BB0ABFF""#EFF""#EFF"
可以看到,超出范围的值都被赋值为了临界值
现在,我们可以重新绘制不同颜色的热图
Heatmap(exp,name="expression",col=col_fun)
name参数的作用是设置颜色图例的名称
颜色并不会受异常值的影响,但是会影响聚类的结果,例如,我们添加一个很大的值
mat-expmat[1,1]--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,,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],,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-expna_index-sample(c(TRUE,FALSE),nrow(exp)*ncol(exp),replace=TRUE,prob=c(1,9))mat_with_na[na_index]-NAHeatmap(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=xqx[1]xqx[2]yqy[1]yqy[2]x=x[l]y=y[l]#计算距离sqrt(sum((x-y)^2))}
聚类
col_fun-colorRamp2(c(-2,0,2),c("#ff7f00","white","#1f78b4"))mat-expmat[sample(1:20,7),sample(1:6,1)]--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=TRUE3.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-exprownames(mat)[5]-paste(c(letters,LETTERS),collapse="")Heatmap(mat,name="expression",col=col_fun,)
默认大小为6厘米,我们可以设置行名或列名的最大宽度
对于基因表达分析,我们的行名通常会设置为geneID,但是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)-END-生信学习手册