• 主页
  • 课程

    关于课程

    • 课程归档
    • 成为一名讲师
    • 讲师信息
    同等学历教学

    同等学历教学

    免费
    阅读更多
  • 特色
    • 展示
    • 关于我们
    • 问答
  • 事件
  • 个性化
  • 博客
  • 联系
  • 站点资源
    有任何问题吗?
    (00) 123 456 789
    weinfoadmin@weinformatics.cn
    注册登录
    恒诺新知
    • 主页
    • 课程

      关于课程

      • 课程归档
      • 成为一名讲师
      • 讲师信息
      同等学历教学

      同等学历教学

      免费
      阅读更多
    • 特色
      • 展示
      • 关于我们
      • 问答
    • 事件
    • 个性化
    • 博客
    • 联系
    • 站点资源

      未分类

      • 首页
      • 博客
      • 未分类
      • circlize 之 circos.heatmap()

      circlize 之 circos.heatmap()

      • 发布者 weinfoadmin
      • 分类 未分类, 老俊俊的生信笔记
      • 日期 2021年9月10日
      • 评论 0评论

      感谢老俊俊的大力支持。我们会每日跟新,欢迎您关注老俊俊的生信笔记。

      circlize 之 circos.heatmap()


      在上期我们讲到使用 circos.rect()基本函数绘制热图,circlize 还有个 circos.heatmap()高级绘制热图函数,让绘制热图更加方便简单,接下来我们介绍 circos.heatmap()函数。

      首先创建一个矩阵:

      set.seed(123)
      mat1 = rbind(cbind(matrix(rnorm(50*5, mean = 1), nr = 50),
                         matrix(rnorm(50*5, mean = -1), nr = 50)),
                   cbind(matrix(rnorm(50*5, mean = -1), nr = 50),
                         matrix(rnorm(50*5, mean = 1), nr = 50))
                  )
      rownames(mat1) = paste0("R", 1:100)
      colnames(mat1) = paste0("C", 1:10)
      mat1 = mat1[sample(100, 100), ] # randomly permute rows
      split = sample(letters[1:5], 100, replace = TRUE)
      split = factor(split, levels = letters[1:5])

      绘制标准热图:

      library(ComplexHeatmap)
      Heatmap(mat1, row_split = split)

      1、输入数据

      circos.heatmap()的输入应该是一个矩阵(或一个将被转换为单列矩阵的向量)。如果将矩阵划分为多个组,则必须使用 split 参数指定分类变量。注意,split 的值应该是字符向量或因子。如果是数字向量,则在内部将其转换为字符。

      必须用定义的颜色模式指定 col 参数。如果矩阵是连续的数字,col 的 value 应该是 colorRamp2()生成的颜色映射,如果矩阵是字符,col 的 value 应该是一个命名的颜色向量。

      library(circlize) # >= 0.4.10
      # 设置颜色
      col_fun1 = colorRamp2(c(-2, 0, 2), c("blue", "white", "red"))
      # 绘图
      circos.heatmap(mat1, split = split, col = col_fun1)
      circos.clear()

      如果未指定 split,则只有一个热图的大扇区:

      circos.heatmap(mat1, col = col_fun1)
      circos.clear()

      2、环形布局

      在绘制圆形图之前可以通过 circos.par()控制圆形布局。

      可以在 circos.heatmap()函数中控制热图轨道,如轨迹高度和轨道背景等:

      circos.par(start.degree = 90, gap.degree = 10)
      circos.heatmap(mat1, split = split, col = col_fun1, track.height = 0.4,
          bg.border = "green", bg.lwd = 2, bg.lty = 2, show.sector.labels = TRUE)
      circos.clear()

      如果 split 参数的值是一个因子,那么因子级别的顺序将控制热图的顺序。如果 split 是一个简单向量,则 heatmap 的顺序是 unique(split):

      # note since circos.clear() was called in the previous plot,
      # now the layout starts from theta = 0 (the first sector is 'e')
      circos.heatmap(mat1, split = factor(split, levels = c("e", "d", "c", "b", "a")),
          col = col_fun1, show.sector.labels = TRUE)
      circos.clear()

      3、聚类树和行名

      默认情况下,数值矩阵是按行聚类的,dend.side 参数控制树状图相对于热图轨道的位置。注意,树状图在一个独立的轨道上:

      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside")
      circos.clear()
      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "outside")
      circos.clear()

      dend.track.height 参数控制树的高度。rownames.side 参数控制行名的方向:

      circos.heatmap(mat1, split = split, col = col_fun1, rownames.side = "inside")
      circos.clear()
      text(0, 0, 'rownames.side = "inside"')
      circos.heatmap(mat1, split = split, col = col_fun1, rownames.side = "outside")
      circos.clear()
      text(0, 0, 'rownames.side = "outside"')

      矩阵的行名和树状图都可以画出来。当然,它们不可能在热图轨道的同一侧:

      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside",
          rownames.side = "outside")
      circos.clear()
      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "outside",
          rownames.side = "inside")
      circos.clear()

      行名的图形参数可以设置为长度与矩阵中的行数相同的标量或向量:

      circos.heatmap(mat1, split = split, col = col_fun1, rownames.side = "outside",
          rownames.col = 1:nrow(mat1) %% 10 + 1,
          rownames.cex = runif(nrow(mat1), min = 0.3, max = 2),
          rownames.font = 1:nrow(mat1) %% 4 + 1)
      circos.clear()

      4、聚类

      默认情况下,数值矩阵按行聚类。cluster 参数可以设置为 FALSE 来关闭聚类。

      当然,当关闭了聚类选项时,即使设置了 dend.side参数,也没有聚类树图:

      circos.heatmap(mat1, split = split, cluster = FALSE, col = col_fun1)
      circos.clear()

      clustering.method 和 distance.method 控制聚类方法和计算距离方法。

      注意,circos.heatmap()不支持对列聚类,若需要对列聚类,最好在绘图前对列聚好类:

      column_od = hclust(dist(t(mat1)))$order
      circos.heatmap(mat1[, column_od])
      circos.clear()

      5、树图回调

      回调函数可以应用到每个在相应扇区生成的树状图上。回调函数编辑树状图,如 1:重新排列树状图,或 2:给系统树图设置颜色。

      需要自定义 dend.callback 回调函数,至少包含 3 个参数:

      • dend:当前扇区的树。
      • m:当前扇区的矩阵。
      • si:扇区的所以或者名字。

      默认的回调函数定义如下,它通过加权矩阵行平均值来重新排列树状图:

      function(dend, m, si) reorder(dend, rowMeans(m))

      下面的例子通过 dendsort::dendsort()对每个扇区的树图重新排序:

      library(dendsort)
      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside",
          dend.callback = function(dend, m, si) {
              dendsort(dend)
          }
      )
      circos.clear()

      我们可以使用 denextend 包中的 color_branches()来渲染树状图的边缘。例如,为五个扇区的树状图分配不同的颜色。这里,树状图轨迹的高度通过 dend.track.height 参数控制:

      library(dendextend)
      dend_col = structure(1:5, names = letters[1:5])
      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside",
          dend.track.height = 0.2,
          dend.callback = function(dend, m, si) {
              # when k = 1, it renders one same color for the whole dendrogram
              color_branches(dend, k = 1, col = dend_col[si])
          }
      )
      circos.clear()

      或者如果矩阵没有被分割,我们可以用不同的颜色给子树状图赋值:

      circos.heatmap(mat1, col = col_fun1, dend.side = "inside",
          dend.track.height = 0.2,
          dend.callback = function(dend, m, si) {
              color_branches(dend, k = 4, col = 2:5)
          }
      )
      circos.clear()

      6、多个轨道的热图

      如果绘制一个只包含一个热图轨道的环形图,那么使用 circos.heatmap()非常简单。如果你绘制一个包含多个轨道的更复杂的环形图,接下来了解更多的功能。

      绘制两层热图:

      mat2 = mat1[sample(100, 100), ] # randomly permute mat1 by rows
      col_fun2 = colorRamp2(c(-2, 0, 2), c("green", "white", "red"))

      circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "outside")
      circos.heatmap(mat2, col = col_fun2)
      circos.clear()

      交换颜色,聚类还是在第一个轨道:

      circos.heatmap(mat2, split = split, col = col_fun2, dend.side = "outside")
      circos.heatmap(mat1, col = col_fun1)
      circos.clear()

      对内外两个热图聚类:

      circos.heatmap.initialize(mat1, split = split)
      circos.heatmap(mat2, col = col_fun2, dend.side = "outside")
      circos.heatmap(mat1, col = col_fun1)
      circos.clear()

      两个热图具有不同列数:

      circos.heatmap.initialize(mat1, split = split)
      circos.heatmap(mat1[, 1:5], col = col_fun1)
      circos.heatmap(mat1[, 6:10], col = col_fun1)
      circos.clear()

      7、添加其它图形

      在完成热图布局之后,可以通过特殊变量 CELL_META 检索用于轨道/扇区/单元格的基本信息。扇区/单元格的数据为如下,它们对于正确对应的热图轨道非常重要:

      • CELL_META$dend:当前扇区的树信息。
      • CELL_META$order:当前扇区聚类后的矩阵顺序信息。
      • CELL_META$subset:完整矩阵的子集,升序排列。

      下面是示例圆形热图中第一个扇区的信息输出:

      CELL_META$row_dend
      ## 'dendrogram' with 2 branches and 14 members total, at height 10.51736

      CELL_META$row_order
      ## [1]  2  6  4 12  8  1  5 10  7  9 13 11  3 14

      CELL_META$subset
      ## [1]  8  9 14 18 20 37 55 62 66 72 78 85 93 97

      在下面的例子中,我添加了一个轨迹,它可视化了 mat1 中前五列的行表示。我添加了 cell.padding = c(0.02, 0, 0.02, 0),使最大和最小点不会与单元格的顶部和底部边界重叠:

      circos.heatmap(mat1, split = split, col = col_fun1)
      row_mean = rowMeans(mat1[, 1:5])
      circos.track(ylim = range(row_mean), panel.fun = function(x, y) {
          y = row_mean[CELL_META$subset]
          y = y[CELL_META$row_order]
          circos.lines(CELL_META$cell.xlim, c(0, 0), lty = 2, col = "grey")
          circos.points(seq_along(y) - 0.5, y, col = ifelse(y > 0, "red", "blue"))
      }, cell.padding = c(0.02, 0, 0.02, 0))
      circos.clear()

      类似地,如果将点轨迹作为第一个轨迹放置,则布局应提前初始化:

      circos.heatmap.initialize(mat1, split = split)
      # This is the same as the previous example
      circos.track(ylim = range(row_mean), panel.fun = function(x, y) {
          y = row_mean[CELL_META$subset]
          y = y[CELL_META$row_order]
          circos.lines(CELL_META$cell.xlim, c(0, 0), lty = 2, col = "grey")
          circos.points(seq_along(y) - 0.5, y, col = ifelse(y > 0, "red", "blue"))
      }, cell.padding = c(0.02, 0, 0.02, 0))
      circos.heatmap(mat1, col = col_fun1) # no need to specify 'split' here
      circos.clear()

      添加 boxplot:

      circos.heatmap(mat1, split = split, col = col_fun1)
      circos.track(ylim = range(mat1), panel.fun = function(x, y) {
          m = mat1[CELL_META$subset, 1:5, drop = FALSE]
          m = m[CELL_META$row_order, , drop = FALSE]
          n = nrow(m)
          # circos.boxplot is applied on matrix columns, so here we transpose it.
          circos.boxplot(t(m), pos = 1:n - 0.5, pch = 16, cex = 0.3)
          circos.lines(CELL_META$cell.xlim, c(0, 0), lty = 2, col = "grey")
      }, cell.padding = c(0.02, 0, 0.02, 0))
      circos.clear()

      8、添加注释

      扇区的标签可以通过设置 show.sector.labels = TRUE 来添加,但是,这并不提供对标签的任何细节调整。用户可以通过 panel.fun 函数来自定义自己的标签。如下。在这里,标签被添加到距离热图轨道 y 方向上的偏移量 2mm 的地方。

      这里设置了 track.index = get.current.track.index()以确保标签总是添加到正确的轨道中:

      circos.heatmap(mat1, split = split, col = col_fun1)
      circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {
          circos.text(CELL_META$xcenter, CELL_META$cell.ylim[2] + convert_y(2, "mm"),
              paste0("this is group ", CELL_META$sector.index),
              facing = "bending.inside", cex = 0.8,
              adj = c(0.5, 0), niceFacing = TRUE)
      }, bg.border = NA)
      circos.clear()

      circos.heatmap()不直接支持矩阵的列名,但也可以通过自定义 panel.fun 轻松添加列名。在下面的例子中,设置了更大的空间(10 度,用户通常需要尝试几个值来获得最佳空间)后的最后一个扇区(第五扇区)的间隙。在 circos.par()中的 parameter 之后,然后在 panel.fun 的最后一个扇区中绘制列名:

      circos.par(gap.after = c(2, 2, 2, 2, 10))
      circos.heatmap(mat1, split = split, col = col_fun1, track.height = 0.4)
      circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {
          if(CELL_META$sector.numeric.index == 5) { # the last sector
              cn = colnames(mat1)
              n = length(cn)
              circos.text(rep(CELL_META$cell.xlim[2], n) + convert_x(1, "mm"),
                  1:n - 0.5, cn,
                  cex = 0.5, adj = c(0, 0.5), facing = "inside")
          }
      }, bg.border = NA)
      circos.clear()

      给列添加分组:

      circos.par(gap.after = c(2, 2, 2, 2, 10))
      circos.heatmap(mat1, split = split, col = col_fun1, track.height = 0.4)
      circos.track(track.index = get.current.track.index(), panel.fun = function(x, y) {
          if(CELL_META$sector.numeric.index == 5) { # the last sector
              circos.rect(CELL_META$cell.xlim[2] + convert_x(1, "mm"), 0,
                          CELL_META$cell.xlim[2] + convert_x(5, "mm"), 5,
                          col = "orange", border = NA)
              circos.text(CELL_META$cell.xlim[2] + convert_x(3, "mm"), 2.5,
                          "group 1", cex = 0.5, facing = "clockwise")

              circos.rect(CELL_META$cell.xlim[2] + convert_x(1, "mm"), 5,
                          CELL_META$cell.xlim[2] + convert_x(5, "mm"), 10,
                          col = "pink", border = NA)
              circos.text(CELL_META$cell.xlim[2] + convert_x(3, "mm"), 7.5,
                          "group 2", cex = 0.5, facing = "clockwise")
          }
      }, bg.border = NA)
      circos.clear()

      添加图例:

      circos.heatmap(mat1, split = split, col = col_fun1)
      circos.clear()

      library(ComplexHeatmap)
      lgd = Legend(title = "mat1", col_fun = col_fun1)
      grid.draw(lgd)

      9、绘制复杂热图

      具体示例和代码就不展示了,感兴趣的可以去搜索一下,大概是下面这样子的:


                 



      发现更多精彩

      关注公众号

      欢迎小伙伴留言评论!

      点击我留言!

      今天的分享就到这里了,敬请期待下一篇!

      最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!

      如果觉得对您帮助很大,打赏一下吧!

      请关注“恒诺新知”微信公众号,感谢“R语言“,”数据那些事儿“,”老俊俊的生信笔记“,”冷🈚️思“,“珞珈R”,“生信星球”的支持!

      • 分享:
      作者头像
      weinfoadmin

      上一篇文章

      circlize 之 Advanced layout
      2021年9月10日

      下一篇文章

      circlize 之 Implement high-level circular plots
      2021年9月10日

      你可能也喜欢

      2-1675088548
      lncRNA和miRNA生信分析系列讲座免费视频课和课件资源包,干货满满
      30 1月, 2023
      9-1675131201
      如何快速批量修改 Git 提交记录中的用户信息
      26 1月, 2023
      8-1678501786
      肿瘤细胞通过改变CD8+ T细胞中的丙酮酸利用和琥珀酸信号来调控抗肿瘤免疫应答。
      7 12月, 2022

      留言 取消回复

      要发表评论,您必须先登录。

      搜索

      分类

      • R语言
      • TCGA数据挖掘
      • 单细胞RNA-seq测序
      • 在线会议直播预告与回放
      • 数据分析那些事儿分类
      • 未分类
      • 生信星球
      • 老俊俊的生信笔记

      投稿培训

      免费

      alphafold2培训

      免费

      群晖配置培训

      免费

      最新博文

      Nature | 单细胞技术揭示衰老细胞与肌肉再生
      301月2023
      lncRNA和miRNA生信分析系列讲座免费视频课和课件资源包,干货满满
      301月2023
      如何快速批量修改 Git 提交记录中的用户信息
      261月2023
      logo-eduma-the-best-lms-wordpress-theme

      (00) 123 456 789

      weinfoadmin@weinformatics.cn

      恒诺新知

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      链接

      • 课程
      • 事件
      • 展示
      • 问答

      支持

      • 文档
      • 论坛
      • 语言包
      • 发行状态

      推荐

      • iHub汉语代码托管
      • iLAB耗材管理
      • WooCommerce
      • 丁香园论坛

      weinformatics 即 恒诺新知。ICP备案号:粤ICP备19129767号

      • 关于我们
      • 博客
      • 联系
      • 成为一名讲师

      要成为一名讲师吗?

      加入数以千计的演讲者获得100%课时费!

      现在开始

      用你的站点账户登录

      忘记密码?

      还不是会员? 现在注册

      注册新帐户

      已经拥有注册账户? 现在登录

      close
      会员购买 你还没有登录,请先登录
      • ¥99 VIP-1个月
      • ¥199 VIP-半年
      • ¥299 VIP-1年
      在线支付 激活码

      立即支付
      支付宝
      微信支付
      请使用 支付宝 或 微信 扫码支付
      登录
      注册|忘记密码?