美文网首页R作图R画图生信绘图
热图如何展示特定行名,缩放单元格大小?

热图如何展示特定行名,缩放单元格大小?

作者: 数据可视化艺术 | 来源:发表于2021-05-19 22:28 被阅读0次

    今天结合nature medicine中的一篇文章,和大家分享下热图的绘制,主要亮点功能是:
    (1)名称太多看不清,如何只展示特定的名称?
    (2)数据太密集,如何快速调整单元格的宽和高?

    论文页面

    image.png

    文章链接https://www.nature.com/articles/s41591-020-0944-y

    代码及数据https://github.com/ajwilk/2020_Wilk_COVID

    拟复现图片样式:Fig2中的热图样式

    图1 拟复现图片样式

    代码实现

    使用数据:数据大家可以通过上述链接下载,附件是一个rds文件(1.5G,一般电脑慎加载会卡死的), 基因云平台(https://www.genescloud.cn)已经整理了一个示例数据,可以在线选择使用。具体可参考下图7 云端数据选择。

    图2 示例数据

    按照惯例,我们先画一个基本的热图。

    library(pheatmap)     
    library(grid)    
    mat <- read.delim("heatmap.txt",sep="\t",row.names=1)
    pheatmap(mat)
    
    图3 初始热图

    上图样式不是很好看,存在以下几点需要完善:①颜色不是很好看,且有灰色边框线条;②行名有很多重叠无法识别;③ 热图缺少分组信息, 接下来我们通过代码继续完善。

    # 设置颜色
    color <- c("blue", "white", "red")
    myColor <- colorRampPalette(color)(100)
    
    # 添加分组信息
    annotation_col <- data.frame(Group = factor(rep(c("T", "C"),4)))
    rownames(annotation_col) <- colnames(mat)
    
    # 绘制热图
    p1 <- pheatmap(mat,color = myColor,
                   border_color=NA, 
                   annotation_col = annotation_col) 
    
    图4 美化后热图一

    接下来通过调整单元格高度,使得文字错开。

    # 调整单元格高度,避免文字重叠
    p1 <- pheatmap(mat,color = myColor,
                   border_color=NA, 
                   annotation_col = annotation_col,
                   cellheight=10)
    
    图5 美化后热图二

    上图通过调整单元格高度调整,文字是清晰可分辨了,但是图片的整体高度会被拉长,放在文章里面不太方便查看。那么我们是否可以只展示特定的行名呢? 首先我们来看下文中提及的,可以实现只展示特定行名的函数:

    # 展示特定行名函数
    add.flag <- function(pheatmap,
                         kept.labels,
                         repel.degree) {
    
      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)
    }
    

    函数写好了,接下来我们看看具体效果。本示例随机抽取20个行名,添加到原来的热图中。具提代码如下,最终效果图如图6所示。

    # 这里随机抽取20个基因进行展示
    gene_name<-sample(rownames(mat),20)
    add.flag(p1,kept.labels = gene_name,repel.degree = 0.2)</pre>
    
    图6 美化后热图三

    到此我们就成功的通过代码实现了一幅含有分组信息,只展示特定行名的热图,那么如何不通过代码实现呢?接下来,给大家分享下基因云(https://www.genescloud.cn)的“交互热图”,帮助你“0”代码快速制作漂亮的上述图表,同时还提供多种样式的在线调整。

    无代码实现

    1 准备数据

    为了方便大家学习实践,基因云平台已整合该文章数据,进入“交互热图”绘图页面,直接通过【文件上传→云端文件→公共数据】按照路径: Home>ref_data>COVID-19_data>交互热图,即可选择使用。

    image 图7 云端数据选择

    2 提交绘图

    选择好数据和分组文件后,一键提交绘图。

    图8 快速提交页面

    3 参数调整

    (1)显示特定基因名称:在图表调整里面,选择【显示名称→行/行列】,下方会出现所有行名列表,可随意勾选你想要展示的名称。

    图9 显示特定基因名称

    (2)随意伸缩单元格宽高:在图表调整栏,随意拖动【单元格宽度/高度】对应的滑动控制条,可随意更改热图单元格的宽和高。

    图10 调整单元格长宽

    相关文章

      网友评论

        本文标题:热图如何展示特定行名,缩放单元格大小?

        本文链接:https://www.haomeiwen.com/subject/qcumjltx.html