自定义你的pheatmap热图

马拉松课程学习群有学员提问,她参考了一个自定义函数修改pheatmap热图,但是一直报错。其实是因为她选取的基因超出了热图里面的全部基因,但是如果辩证思维不够,就会怀疑函数本身的问题。

我给学员了一个很简单的例子, 就是自己创造一个数据,然后使用 https://github.com/ajwilk/2020_Wilk_COVID 里面的自定义函数, 全部的代码如下所示:

df=as.data.frame(matrix(rnorm(2600),100))
library(pheatmap)
pheatmap(df)
rownames(df)
add.flag <- function(pheatmap,
                     kept.labels,
                     repel.degree) {
  
  # repel.degree = number within [0, 1], which controls how much 
  #                space to allocate for repelling labels.
  ## repel.degree = 0: spread out labels over existing range of kept labels
  ## repel.degree = 1: spread out labels over the full y-axis
  
  heatmap <- pheatmap$gtable
  
  new.label <- heatmap$grobs[[which(heatmap$layout$name == "row_names")]] 
  
  # keep only labels in kept.labels, replace the rest with ""
  new.label$label <- ifelse(new.label$label %in% kept.labels, 
                            new.label$label, "")
  
  # calculate evenly spaced out y-axis positions
  repelled.y <- function(d, d.select, k = repel.degree){
    # d = vector of distances for labels
    # d.select = vector of T/F for which labels are significant
    
    # recursive function to get current label positions
    # (note the unit is "npc" for all components of each distance)
    strip.npc <- function(dd){
      if(!"unit.arithmetic" %in% class(dd)) {
        return(as.numeric(dd))
      }
      
      d1 <- strip.npc(dd$arg1)
      d2 <- strip.npc(dd$arg2)
      fn <- dd$fname
      return(lazyeval::lazy_eval(paste(d1, fn, d2)))
    }
    
    full.range <- sapply(seq_along(d), function(i) strip.npc(d[i]))
    selected.range <- sapply(seq_along(d[d.select]), function(i) strip.npc(d[d.select][i]))
    
    return(unit(seq(from = max(selected.range) + k*(max(full.range) - max(selected.range)),
                    to = min(selected.range) - k*(min(selected.range) - min(full.range)), 
                    length.out = sum(d.select)), 
                "npc"))
  }
  new.y.positions <- repelled.y(new.label$y,
                                d.select = new.label$label != "")
  new.flag <- segmentsGrob(x0 = new.label$x,
                           x1 = new.label$x + unit(0.15, "npc"),
                           y0 = new.label$y[new.label$label != ""],
                           y1 = new.y.positions)
  
  # shift position for selected labels
  new.label$x <- new.label$x + unit(0.2, "npc")
  new.label$y[new.label$label != ""] <- new.y.positions
  
  # add flag to heatmap
  heatmap <- gtable::gtable_add_grob(x = heatmap,
                                     grobs = new.flag,
                                     t = 4, 
                                     l = 4
  )
  
  # replace label positions in heatmap
  heatmap$grobs[[which(heatmap$layout$name == "row_names")]] <- new.label
  
  # plot result
  grid.newpage()
  grid.draw(heatmap)
  
  # return a copy of the heatmap invisibly
  invisible(heatmap)
}

library(grid)
(gene_name<-sample(rownames(df),5))
p1<-pheatmap(df)
add.flag(p1,
         kept.labels = gene_name,
         repel.degree = 0.2)

可以看到, 自己的定义的一个随机数组成的表达量矩阵被绘制了热图,而且自己随机挑选的5个行名也被重点显示出来了:

自定义热图

如果是以  airway 这样的表达量矩阵作为示例,你会发现这个自定义你的pheatmap热图小技巧超级有用,比如

suppressPackageStartupMessages( library( "airway" ) )
library("airway")
data(airway)
ensembl_matrix=assay(airway)
ensembl_matrix[1:4,1:4] 
dim(ensembl_matrix) 
library(AnnoProbe)
gs=annoGene(rownames(ensembl_matrix),'ENSEMBL','human')
head(gs)
as.data.frame(tail(sort(table(gs$biotypes))))
pd_genes=gs[gs$biotypes=='protein_coding',] 
pd_matrix=ensembl_matrix[rownames(ensembl_matrix) %in% pd_genes$ENSEMBL,] 
rownames(pd_matrix)=pd_genes[match(rownames(pd_matrix),pd_genes$ENSEMBL),1]
pd_matrix[1:4,1:4] 
pd_matrix=log2(edgeR::cpm(pd_matrix)+1)

dat=pd_matrix
cg=names(tail(sort(apply(dat,1,sd)),1000))#apply按行('1'是按行取,'2'是按列取)取每一行的方差,从小到大排序,取最大的1000个
library(pheatmap)
pheatmap(dat[cg,],show_colnames =F,show_rownames = F) #对那些提取出来的1000个基因所在的每一行取出,组合起来为一个新的表达矩阵
n=t(scale(t(dat[cg,]))) # 'scale'可以对log-ratio数值进行归一化
n[n>2]=2 
n[n< -2]= -2
n[1:4,1:4]
pheatmap(n,
         show_colnames =F,
         show_rownames = T)

出图会非常丑:

基因重叠在一起

因为我们挑选了1000个基因,无论你如何调整这个图的比例大小,都是无济于事。但是如果你使用我们上面介绍的技巧:

library(grid)
(gene_name<-sample(rownames(n),5))
p1<-pheatmap(n)
add.flag(p1,
         kept.labels = gene_name,
         repel.degree = 0.2)

见证奇迹的时刻:

重点展现你的基因列表

你重点想展示的基因,一目了然。

(0)

相关推荐

  • ComplexHeatmap绘制热图详细步骤

    pheatmap是一个非常受欢迎的绘制热图的R包.ComplexHeatmap包即是受之启发而来.你可以发现Heatmap()函数中很多参数都与pheatmap()相同.在pheatmap的时代(请允 ...

  • 技术贴 | R语言:手把手教你画pheatmap热图

    导读: pheatmap默认会对输入矩阵数据的行和列同时进行聚类,但是也可以通过布尔型参数cluster_rows和cluster_cols设置是否对行或列进行聚类,具体看分析需求.利用display ...

  • 技术贴 | R语言pheatmap聚类分析和热图

    本文由阿童木根据实践经验而整理,希望对大家有帮助. 原创微文,欢迎转发转载. 导读 pheatmap默认会对输入矩阵数据的行和列同时进行聚类,但是也可以通过布尔型参数cluster_rows和clus ...

  • 多分组热图不用愁,Pheatmap来帮忙

    [Pheatmap 绘制多分组热图] 热图作为实验数据分布情况的直观展示方法,已经成为高分文章的不错选择,它不仅可以对数据质量进行具像化展示,还可以对数据和样品进行聚类.在R中有多个包均可绘制热图,今 ...

  • 热图怎么做? | 热图函数pheatmap() | | 百迈客生物基因

    是不是会经常绘制热图?那热图怎么做?先看一眼这个函数的参数,这么多,而且最后还有省略号.那么我们应该怎么合理使用这些参数让你的热图看起来更加高大上呢? pheatmap(mat, color = co ...

  • 八大数据分析模型之——热图分析模型(四)

    诸葛君说:产品/运营们最痛苦的莫过于说服开发部门同意我们的网页改版方案,他们往往会充满怀疑的反问:为什么要这样做?总之,在你无法证明"你是对的"情况下,所有的沟通仿佛都站不住脚,今 ...

  • 基础技术 | 使用条件格式创建热图(续)

    在<基础技术 | 使用条件格式创建热图>中,我们介绍了使用条件格式的色阶功能创建具有三种不同背景颜色的热图,使数据可视化.在此基础上,结合表单控件滚动条,创建了随滚动条变化的动态热图. 下 ...

  • 基础技术 | 使用条件格式创建热图

    热图是一种数据可视化的表示形式,可以快速显示数据集的比较视图. 在Excel中,使用条件格式,可以基于值高亮显示单元格.然后,改变单元格中的值,单元格的颜色/格式将基于在条件格式中指定的规则自动更新热 ...

  • 技术贴 | R语言:构建一个转录代谢互作调控网络:(二)热图的美化以及大样本分组信息的快速注释

    本文由可爱的乔巴根据实践经验而整理,希望对大家有帮助. 原创微文,欢迎转发转载. 导读 上期介绍了利用WGCNA包中的Cor函数和corPvalueStudent函数计算两组小样本的相关性并进行热图可 ...

  • 技术贴 | R语言:大样本多组学的相关性计算、热图绘制

    本文由可爱的乔巴根据实践经验而整理,希望对大家有帮助. 原创微文,欢迎转发转载. 导读 上期介绍了利用psych包计算两组小样本的相关性并进行热图可视化,但当样本数据量非常大时,psych包会耗费的时 ...