circlize 之 Implement high-level circular plots
1、环状条形图
circlize 提供了 circos.barplot()
函数来绘制环状条形图:
# 制造数据
category = paste0("category", "_", 1:9)
percent = sort(sample(40:80, 9))
color = rev(rainbow(length(percent)))
# 绘图
library(circlize)
# 设置旋转角度,单元格填充
circos.par("start.degree" = 90, cell.padding = c(0, 0, 0, 0))
# 'a` just means there is one sector
# 只有一个扇区a
circos.initialize("a", xlim = c(0, 100))
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(0, 9), 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.05, 0.5), cex = 0.8)
breaks = seq(0, 85, 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(0, 0, 0, 0))
circos.initialize("a", xlim = c(0, n)) # only one sector
circos.track(ylim = c(0, 1), bg.border = NA, track.height = 0.3,
panel.fun = function(x, y) {
for(i in seq_len(n)) {
circos.text(i-0.5, 0, labels[i], adj = c(0, 0.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(-2, 0, 2), c("green", "black", "red"))
# 定义扇区
sectors = rep(letters[1:2], times = c(30, 70))
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(0, 0, 0, 0), gap.degree = 5)
circos.initialize(sectors, xlim = cbind(c(0, 0), table(sectors)))
circos.track(ylim = c(0, 10), 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(),它可以绘制漂亮的圆形热图。
发现更多精彩
关注公众号
欢迎小伙伴留言评论!
今天的分享就到这里了,敬请期待下一篇!
最后欢迎大家分享转发,您的点赞是对我的鼓励和肯定!
如果觉得对您帮助很大,打赏一下吧!