# `circlize`包

`circlize`包在德国癌症中心的华人博士Zuguang Gu开发的，有兴趣的可以去看看他的Github主页。这个包有两个文档，一个是介绍基本原理的绘制简单圈圈图的，也是本次要介绍的。另外一份文档专门介绍基因组数据绘制圈圈图Genomic Circos Plot,我自己还没看完，下次再介绍。

# 用`circlize`绘制圈圈图

``````library(circlize)
# 简单创建一个数据集
set.seed(999)
n <- 1000
a <- data.frame(factors = sample(letters[1:8], n, replace = TRUE), x = rnorm(n), y = runif(n))
``````

## 绘制第一个`track`

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x) #初始化，factors来控制track数目，初始化里只有x， 没有y。这一步相当于ggplot()
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) {
circos.axis()})
col <- rep(c("#FF0000", "#00FF00"), 4) #自定义一下颜色# 这里先解释一下，一个track有好几个cell，具体数目由factors决定的，向本数据集中factors有八个，因此绘制一个track，其包含八个cell。含有前缀circos.track的函数会在所有的cel里添加基本元素，而只有前缀circos.的函数可以在特定的track、cell里添加基本元素。具体看下演示。
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5) #所有的cell里都绘制点图
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1) #在track 1中的标记为a的cell里添加
textcircos.text(1, 0.5, "right", sector.index = "a")
circos.clear()
``````

## 接下来绘制第二个`track`

`circos.trackHist`添加柱状图，由于柱状图相对高级一点，因此`circos.trackHist`会自动创建一个`track`，无需我们`circos.trackPlotRegion`进行创建。

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x)
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) {
circos.axis()})
col <- rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
bg.col <- rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(a\$factors, a\$x, bg.col = bg.col, col = NA)
circos.clear()
``````

## 创建第三个`track`

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x)
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) {
circos.axis()})
col <- rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
bg.col <- rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(a\$factors, a\$x, bg.col = bg.col, col = NA)
circos.trackPlotRegion(factors = a\$factors, x = a\$x, y = a\$y,
panel.fun = function(x, y) {
grey = c("#FFFFFF", "#CCCCCC", "#999999")
sector.index = get.cell.meta.data("sector.index") #这个是第三个track，因为我们刚刚创建，这里这一步不用也可。
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), sector.index)
circos.points(x[1:10], y[1:10], col = "red", pch = 16, cex = 0.6)
circos.points(x[11:20], y[11:20], col = "blue", cex = 0.6)})
circos.clear()
``````

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x)
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) {
circos.axis()})col <- rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
bg.col <- rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(a\$factors, a\$x, bg.col = bg.col, col = NA)
circos.trackPlotRegion(factors = a\$factors, x = a\$x, y = a\$y,
panel.fun = function(x, y) {
grey = c("#FFFFFF", "#CCCCCC", "#999999")
sector.index = get.cell.meta.data("sector.index")
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), sector.index)
circos.points(x[1:10], y[1:10], col = "red", pch = 16, cex = 0.6)
circos.points(x[11:20], y[11:20], col = "blue", cex = 0.6)})
# update第2个track中标记为d的sector
circos.updatePlotRegion(sector.index = "d", track.index = 2)
circos.points(x = -2:2, y = rep(0, 5))
xlim <- get.cell.meta.data("xlim")
ylim <- get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), "updated")
circos.clear()
``````

## 接下来绘制第四个`track`

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x)
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) { circos.axis()})
col <- rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
bg.col <- rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(a\$factors, a\$x, bg.col = bg.col, col = NA)
circos.trackPlotRegion(factors = a\$factors, x = a\$x, y = a\$y,
panel.fun = function(x, y) {
grey = c("#FFFFFF", "#CCCCCC", "#999999")
sector.index = get.cell.meta.data("sector.index")
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), sector.index)
circos.points(x[1:10], y[1:10], col = "red", pch = 16, cex = 0.6)
circos.points(x[11:20], y[11:20], col = "blue", cex = 0.6)})
# update第2个track中标记为d的sector
circos.updatePlotRegion(sector.index = "d", track.index = 2)
circos.points(x = -2:2, y = rep(0, 5))
xlim <- get.cell.meta.data("xlim")
ylim <- get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), "updated")
circos.clear()
circos.trackPlotRegion(factors = a\$factors, y = a\$y)
circos.trackLines(a\$factors[1:100], a\$x[1:100], a\$y[1:100], type = "h")
``````

``````par(mar = c(1, 1, 1, 1), lwd = 0.1, cex = 0.6)
circos.par(track.height = 0.1)
circos.initialize(factors = a\$factors, x = a\$x)
circos.trackPlotRegion(factors = a\$factors, y = a\$y,
panel.fun = function(x, y) { circos.axis()})
col <- rep(c("#FF0000", "#00FF00"), 4)
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
circos.trackPoints(a\$factors, a\$x, a\$y, col = col, pch = 16, cex = 0.5)
circos.text(-1, 0.5, "left", sector.index = "a", track.index = 1)
circos.text(1, 0.5, "right", sector.index = "a")
bg.col <- rep(c("#EFEFEF", "#CCCCCC"), 4)
circos.trackHist(a\$factors, a\$x, bg.col = bg.col, col = NA)
circos.trackPlotRegion(factors = a\$factors, x = a\$x, y = a\$y,
panel.fun = function(x, y) {
grey = c("#FFFFFF", "#CCCCCC", "#999999")
sector.index = get.cell.meta.data("sector.index")
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), sector.index)
circos.points(x[1:10], y[1:10], col = "red", pch = 16, cex = 0.6)
circos.points(x[11:20], y[11:20], col = "blue", cex = 0.6)})
# update第2个track中标记为d的sector
circos.updatePlotRegion(sector.index = "d", track.index = 2)
circos.points(x = -2:2, y = rep(0, 5))
xlim <- get.cell.meta.data("xlim")
ylim <- get.cell.meta.data("ylim")
circos.text(mean(xlim), mean(ylim), "updated")
circos.clear()
circos.trackPlotRegion(factors = a\$factors, y = a\$y)
circos.trackLines(a\$factors[1:100], a\$x[1:100], a\$y[1:100], type = "h")
circos.link("a", 0, "b", 0, h = 0.3) #point to point
circos.link("c", c(-0.5, 0.5), "d", c(-0.5, 0.5), col = "red", border = NA, h = 0.2) #intreval to interval
circos.link("e", 0, "g", c(-1, 1), col = "green", border = "black", lwd = 2, lty = 2) #point to interval
``````

# circlize详述

`circlize`的绘图规则是初始化(`initialize`)-创建`track`-添加图形元素-创建`track`-添加图形元素-…-`circos.clear`。具体参数设置以及解释由于内容太多，有兴趣的可以自己参考文档。 我认为比较重要的是要理解`track``sector`。由于基本所有的图形元素我们都是添加在`sector`

``````par(mar = c(1, 1, 1, 1))
factors <- letters[1:8]
circos.initialize(factors = factors, xlim = c(0, 1)) #初始化# 绘制三个track，并显示具体信息
for (i in 1:3) {
circos.trackPlotRegion(ylim = c(0, 1))}
circos.info(plot = TRUE)
# 通过draw.sector()来高亮某一sector，比如a：
draw.sector(get.cell.meta.data("cell.start.degree", sector.index = "a"),
get.cell.meta.data("cell.end.degree", sector.index = "a"), rou1 = 1, col = "blue")
circos.clear()
``````
``````# 高亮某一track， 比如第一个track：
circos.initialize(factors = factors, xlim = c(0, 1))
for (i in 1:3) {
circos.trackPlotRegion(ylim = c(0, 1))}
circos.info(plot = TRUE)
draw.sector(0, 360, rou1 = get.cell.meta.data("cell.top.radius", track.index = 1),
rou2 = get.cell.meta.data("cell.bottom.radius", track.index = 1), col = "green")
circos.clear()
``````
``````# 高亮某一track某一sector，比如地2、3track中的e、f(sector)：
circos.initialize(factors = factors, xlim = c(0, 1))
for (i in 1:3) { circos.trackPlotRegion(ylim = c(0, 1))}
circos.info(plot = TRUE)
draw.sector(get.cell.meta.data("cell.start.degree", sector.index = "e"),
get.cell.meta.data("cell.end.degree", sector.index = "f"),
get.cell.meta.data("cell.bottom.radius", track.index = 3), col = "red")
circos.clear() #千万别忘了circos.clear，不然下次无法绘图。
``````

# 放大某一特定区域

``````df <- data.frame(factors = sample(letters[1:6], 100, replace = TRUE),
x = rnorm(100),
y = rnorm(100),
stringsAsFactors = FALSE)
# 放大a，b区域
zoom_df <- df %>% dplyr::filter(factors %in% c("a", "b"))
zoom_df\$factors <- paste0("zoom_", zoom_df\$factors)
df2 <- rbind(df, zoom_df)
xrange <- tapply(df2\$x, df2\$factors, function(x) max(x) - min(x))
normal_sector_index <- unique(df\$factors)
zoomed_sector_index <- unique(zoom_df\$factors)
sector.width <- c(xrange[normal_sector_index]/sum(xrange[normal_sector_index]),
xrange[zoomed_sector_index]/sum(xrange[zoomed_sector_index]))
# 绘图
par(mar = c(1, 1, 1, 1))
circos.par(start.degree = 90)
circos.initialize(df2\$factors, x = df2\$x, sector.width = sector.width)
circos.trackPlotRegion(df2\$factors, x = df2\$x, y = df2\$y,
panel.fun = function(x, y) {
circos.points(x, y, col = "red", pch = 16, cex = 0.5)
xlim = get.cell.meta.data("xlim")
ylim = get.cell.meta.data("ylim")
sector.index = get.cell.meta.data("sector.index")
circos.text(mean(xlim), mean(ylim), sector.index, niceFacing = TRUE)})
circos.link("a", get.cell.meta.data("cell.xlim", sector.index = "a"), "zoom_a",
get.cell.meta.data("cell.xlim", sector.index = "zoom_a"), border = NA, col = "red")
``````

circos.clear()

# 举个栗子

``````set.seed(1234)
data <- matrix(rnorm(100 * 10), nrow = 10, ncol = 100)
col <- colorRamp2(c(-2, 0, 2), c("green", "black", "red"))
factors <- rep(letters[1:2], times = c(30, 70))
data_list <- list(a = data[, factors == "a"], b = data[, factors == "b"])
dend_list <- list(a = as.dendrogram(hclust(dist(t(data_list[["a"]])))),
b = as.dendrogram(hclust(dist(t(data_list[["b"]])))))
circos.par(cell.padding = c(0, 0, 0, 0), gap.degree = 5)
circos.initialize(factors = factors, xlim = cbind(c(0, 0), table(factors)))
circos.track(ylim = c(0, 10), bg.border = NA,
panel.fun = function(x, y) {
sector.index = get.cell.meta.data("sector.index")
d = data_list[[sector.index]]
dend = dend_list[[sector.index]]
d2 = d[, order.dendrogram(dend)]
col_data = col(d2)
nr = nrow(d2)
nc = ncol(d2)
for (i in 1:nr) {
circos.rect(1:nc - 1, rep(nr - i, nc), 1:nc, rep(nr - i + 1, nc),
border = col_data[i, ], col = col_data[i, ]) }})
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()
``````

# 多图排列

``````layout(matrix(1:9, 3, 3))
for (i in 1:9) {
factors = letters[1:8]
par(mar = c(0.5, 0.5, 0.5, 0.5))
circos.par(cell.padding = c(0, 0, 0, 0))
circos.initialize(factors = factors, xlim = c(0, 1))
circos.trackPlotRegion(ylim = c(0, 1), track.height = 0.05,
bg.col = rand_color(8), bg.border = NA)
for (i in 1:20) {
se = sample(letters[1:8], 2)
col = rand_color(1, transparency = 0.4), border = NA)
}
circos.clear()
``````

# sessionInfo

``````sessionInfo()
``````
``````## R version 3.4.0 (2017-04-21)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 8.1 x64 (build 9600)
## ## Matrix products: default##
## locale:
## [1] LC_COLLATE=Chinese (Simplified)_China.936
## [2] LC_CTYPE=Chinese (Simplified)_China.936
## [3] LC_MONETARY=Chinese (Simplified)_China.936
## [4] LC_NUMERIC=C
## [5] LC_TIME=Chinese (Simplified)_China.936
## ## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
## ## other attached packages:
## [1] circlize_0.4.0 BiocInstaller_1.26.0 forcats_0.2.0
## [4] stringr_1.2.0 dplyr_0.5.0 purrr_0.2.2.2
## [10] ggplot2_2.2.1 tidyverse_1.1.1.9000
#### loaded via a namespace (and not attached):
## [1] shape_1.4.2 clisymbols_1.2.0 reshape2_1.4.2
## [4] haven_1.0.0 lattice_0.20-35 colorspace_1.3-2
## [7] htmltools_0.3.6 yaml_2.1.14 rlang_0.1.1
## [10] foreign_0.8-68 DBI_0.6-1 modelr_0.1.0
## [16] gtable_0.2.0 cellranger_1.1.0 rvest_0.3.2
## [19] GlobalOptions_0.0.12 psych_1.7.5 evaluate_0.10
## [22] knitr_1.16 parallel_3.4.0 broom_0.4.2
## [25] Rcpp_0.12.11 scales_0.4.1 backports_1.1.0
## [28] formatR_1.5 jsonlite_1.4 boxes_0.0.0.9000
## [31] mnormt_1.5-5 hms_0.3 digest_0.6.12
## [34] stringi_1.1.5 grid_3.4.0 rprojroot_1.2
## [37] tools_3.4.0 magrittr_1.5 lazyeval_0.2.0
## [40] crayon_1.3.2.9000 xml2_1.1.1 lubridate_1.6.0
## [43] assertthat_0.2.0 rmarkdown_1.5 httr_1.2.1
## [46] rstudioapi_0.6 R6_2.2.1 nlme_3.1-131
## [49] compiler_3.4.0
``````

• 序言：七十年代末，一起剥皮案震惊了整个滨河市，随后出现的几起案子，更是在滨河造成了极大的恐慌，老刑警刘岩，带你破解...
沈念sama阅读 156,423评论 4 359
• 序言：滨河连续发生了三起死亡事件，死亡现场离奇诡异，居然都是意外死亡，警方通过查阅死者的电脑和手机，发现死者居然都...
沈念sama阅读 66,339评论 1 289
• 文/潘晓璐 我一进店门，熙熙楼的掌柜王于贵愁眉苦脸地迎上来，“玉大人，你说我怎么就摊上这事。” “怎么了？”我有些...
开封第一讲书人阅读 106,241评论 0 237
• 文/不坏的土叔 我叫张陵，是天一观的道长。 经常有香客问我，道长，这世上最难降的妖魔是什么？ 我笑而不...
开封第一讲书人阅读 43,503评论 0 203
• 正文 为了忘掉前任，我火速办了婚礼，结果婚礼上，老公的妹妹穿的比我还像新娘。我一直安慰自己，他们只是感情好，可当我...
茶点故事阅读 51,824评论 3 285
• 文/花漫 我一把揭开白布。 她就那样静静地躺着，像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上，一...
开封第一讲书人阅读 40,262评论 1 207
• 那天，我揣着相机与录音，去河边找鬼。 笑死，一个胖子当着我的面吹牛，可吹牛的内容都是我干的。 我是一名探鬼主播，决...
沈念sama阅读 31,615评论 2 309
• 文/苍兰香墨 我猛地睁开眼，长吁一口气：“原来是场噩梦啊……” “哼！你这毒妇竟也来了？” 一声冷哼从身侧响起，我...
开封第一讲书人阅读 30,337评论 0 194
• 序言：老挝万荣一对情侣失踪，失踪者是张志新（化名）和其女友刘颖，没想到半个月后，有当地人在树林里发现了一具尸体，经...
沈念sama阅读 33,989评论 1 238
• 正文 独居荒郊野岭守林人离奇死亡，尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
茶点故事阅读 30,300评论 2 240
• 正文 我和宋清朗相恋三年，在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
茶点故事阅读 31,829评论 1 256
• 序言：一个原本活蹦乱跳的男人离奇死亡，死状恐怖，灵堂内的尸体忽然破棺而出，到底是诈尸还是另有隐情，我是刑警宁泽，带...
沈念sama阅读 28,193评论 2 250
• 正文 年R本政府宣布，位于F岛的核电站，受9级特大地震影响，放射性物质发生泄漏。R本人自食恶果不足惜，却给世界环境...
茶点故事阅读 32,753评论 3 230
• 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹，春花似锦、人声如沸。这庄子的主人今日做“春日...
开封第一讲书人阅读 25,970评论 0 8
• 文/苍兰香墨 我抬头看了看天上的太阳。三九已至，却和暖如春，着一层夹袄步出监牢的瞬间，已是汗流浃背。 一阵脚步声响...
开封第一讲书人阅读 26,708评论 0 192
• 我被黑心中介骗来泰国打工， 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留，地道东北人。 一个月前我还...
沈念sama阅读 35,295评论 2 267
• 正文 我出身青楼，却偏偏与公主长得像，于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子，可洞房花烛夜当晚...
茶点故事阅读 35,207评论 2 258