查看原文
其他

circlize 之 Implement high-level circular plots

JunJunLab 老俊俊的生信笔记 2022-08-15

circlize 之 Implement high-level circular plots


1、环状条形图

circlize 提供了 circos.barplot()函数来绘制环状条形图:

# 制造数据
category = paste0("category""_"1:9)
percent = sort(sample(40:809))
color = rev(rainbow(length(percent)))
# 绘图
library(circlize)
# 设置旋转角度,单元格填充
circos.par("start.degree" = 90, cell.padding = c(0000))
# 'a` just means there is one sector
# 只有一个扇区a
circos.initialize("a", xlim = c(0100))
circos.track(ylim = c(0.5, length(percent)+0.5), track.height = 0.8,
    bg.border = NA, panel.fun = function(x, y) {
        xlim = CELL_META$xlim
        circos.segments(rep(xlim[1], 9), 1:9,
                        rep(xlim[2], 9), 1:9,
                        col = "#CCCCCC")
        circos.rect(rep(09), 1:9 - 0.45, percent, 1:9 + 0.45,
            col = color, border = "white")
        circos.text(rep(xlim[1], 9), 1:9,
            paste(category, " - ", percent, "%"),
            facing = "downward", adj = c(1.050.5), cex = 0.8)
        breaks = seq(085, by = 5)
        circos.axis(h = "top", major.at = breaks, labels = paste0(breaks, "%"),
            labels.cex = 0.6)
})
# 清空
circos.clear()


2、直方图

circlize 提供了一个 circos.trackHist()函数,该函数在单元格中绘制直方图。这个函数是一个高级函数,它计算 y 轴上的数据范围并创建一个新的轨道。这个函数的实现很简单,它首先通过 hist()函数计算每个单元格的直方图,然后使用 circos.rect()绘制直方图。

用户可以设置 draw.density = TRUE,通过密度线来显示数据分布。

默认情况下,每个单元格的直方图的 bin.size 是单独计算的,每个单元格之间的 bin.size 是不一样的,所以比较不一致。手动设置 bin.size。将所有单元的大小设置为相同的值有助于比较单元之间的分布。

x = rnorm(1600)
sectors = sample(letters[1:16], 1600, replace = TRUE)
circos.initialize(sectors, x = x)
# 默认绘制
circos.trackHist(sectors, x = x, col = "#999999",
    border = "#999999")
# 设置bin.size = 0.1
circos.trackHist(sectors, x = x, bin.size = 0.1,
    col = "#999999", border = "#999999")
# draw.density = TRUE
circos.trackHist(sectors, x = x, draw.density = TRUE,
    col = "#999999", border = "#999999")
# 清空
circos.clear()


3、进化树

可视化系统发生树。基本上,一个系统发育树是一个树状图,它是线的组合。在 R 中,有几个类来描述这种类型的树,如 hclust,dendrogram 和 phylo。在这个例子中,我们将演示如何从树状图类中绘制树。然而,其他类可以轻松地转换成树状图。

# 使用ape包的内置数据集
library(ape)
data(bird.orders)
hc = as.hclust(bird.orders)

把树分成 6 个枝,并转化为 dendrogram 对象:

labels = hc$labels  # name of birds
ct = cutree(hc, 6)  # cut tree into 6 pieces
n = length(labels)  # number of bird species
dend = as.dendrogram(hc)

正如我们之前提到的,系统发育树的 x 值实际上是索引。因此,x-lim 只是树中标签的最小和最大索引。因为只有一棵进化树,我们只需要一个大的扇区。

在第一个轨道中,我们绘制了每只鸟的名字,用不同的颜色表示不同的子树。

circos.par(cell.padding = c(0000))
circos.initialize("a", xlim = c(0, n)) # only one sector
circos.track(ylim = c(01), bg.border = NA, track.height = 0.3,
    panel.fun = function(x, y) {
        for(i in seq_len(n)) {
            circos.text(i-0.50, labels[i], adj = c(00.5),
                facing = "clockwise", niceFacing = TRUE,
                col = ct[labels[i]], cex = 0.5)
        }
})

在上面的代码中,将 xlim 设置为 c(0, n)非常重要,因为树状图的叶子是在 x = seq(0.5, n - 0.5)处绘制的。

在第二个轨道中,我们通过 circos.dendrogram()绘制圆形树状图。你可以通过 denextend 包来渲染树状图。

suppressPackageStartupMessages(library(dendextend))
dend = color_branches(dend, k = 6, col = 1:6)
dend_height = attr(dend, "height")
circos.track(ylim = c(0, dend_height), bg.border = NA,
    track.height = 0.4, panel.fun = function(x, y) {
        circos.dendrogram(dend)
})
circos.clear()

默认情况下,树状图面向圆的外部(因此标签也应该添加到树状图的外部)。在 circos.dendrogram()中,可以将 facing 参数设置为 inside,使它们面向 inside。在本例中,首先添加树状轨迹,然后添加标签:

circos.dendrogram(dend, facing = "inside")


4、手动绘制热图

热图,有时结合树状图经常被用来可视化,例如基因表达。热图基本上由矩形组成,因此可以通过 circos.rect()实现:

# 创建矩阵
mat = matrix(rnorm(100*10), nrow = 100, ncol = 10)
# 设置颜色
col_fun = colorRamp2(c(-202), c("green""black""red"))
# 定义扇区
sectors = rep(letters[1:2], times = c(3070))
mat_list = list(a = mat[sectors == "a", ],
                b = mat[sectors == "b", ])
# 聚类
dend_list = list(a = as.dendrogram(hclust(dist(mat_list[["a"]]))),
                 b = as.dendrogram(hclust(dist(mat_list[["b"]]))))

绘制热图:

circos.par(cell.padding = c(0000), gap.degree = 5)
circos.initialize(sectors, xlim = cbind(c(00), table(sectors)))
circos.track(ylim = c(010), bg.border = NA, panel.fun = function(x, y) {
    sector.index = CELL_META$sector.index
    m = mat_list[[sector.index]]
    dend = dend_list[[sector.index]]

    m2 = m[order.dendrogram(dend), ]
    col_mat = col_fun(m2)
    nr = nrow(m2)
    nc = ncol(m2)
    for(i in 1:nc) {
        circos.rect(1:nr - 1, rep(nc - i, nr),
            1:nr, rep(nc - i + 1, nr),
            border = col_mat[, i], col = col_mat[, i])
    }
})

因为有两个树状图,所以将两个树状图的高度设为相同的尺度是很重要的。我们计算了两个树状图的最大高度,并将其设为第二道轨迹的 ylim:

max_height = max(sapply(dend_list, function(x) attr(x, "height")))
circos.track(ylim = c(0, max_height), bg.border = NA, track.height = 0.3,
    panel.fun = function(x, y) {
        sector.index = get.cell.meta.data("sector.index")
        dend = dend_list[[sector.index]]
        circos.dendrogram(dend, max_height = max_height)
})
circos.clear()

在下一章中,我们将介绍一个高级函数 circos.heatmap(),它可以绘制漂亮的圆形热图。

发现更多精彩

关注公众号

欢迎小伙伴留言评论!

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

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

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

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存