弦图常用于表示两组或多组成员之间的连接关系。如下简单学习circlizeChordDiagram()绘制弦图的基础用法

  • 参考教程:https://jokergoo.github.io/circlize_book/book/the-chorddiagram-function.html

0、数据输入

对于matrix:

  • 默认row组表示sender,column表示receiver,矩阵值表示link的强度;

对于data.frame

  • 默认第一列表示sender,第二列表示receiver,第三列表示link的强度

之后的示例学习中主要以matrix的用法为主。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## (1) matrix
set.seed(999)
mat = matrix(sample(18, 18), 3, 6) 
rownames(mat) = paste0("S", 1:3)
colnames(mat) = paste0("E", 1:6)
mat
#    E1 E2 E3 E4 E5 E6
# S1  4 14 13 17  5  2
# S2  7  1  6  8 12 15
# S3  9 10  3 16 11 18

## (2) data.frame
df = data.frame(from = rep(rownames(mat), times = ncol(mat)),
                to = rep(colnames(mat), each = nrow(mat)),
                value = as.vector(mat),
                stringsAsFactors = FALSE)
head(df)
#    from to value
# 1    S1 E1     4
# 2    S2 E1     7
# 3    S3 E1     9
# 4    S1 E2    14
# 5    S2 E2     1
# 6    S3 E2    10

1、构图要素

1
2
3
4
5
6
library(circlize)

chordDiagram(mat)
# title("Chod Diagram")

# chordDiagram(df)
image-20230417102206316
  • 如上图形,弦图主要由内部表示连接关系的link与外部的3层track构成。tracks由里到外分别是表示组成员的grid/sector、axis、name。后面的参数设置即主要对上述细节进行调整。

  • 由于每一次参数修改都有可能对之后的绘图产生痕迹,因此建议绘图后运行命令circos.clear()

2、grid等tracks设置

  • (1)grid顺序
1
2
3
4
chordDiagram(mat, 
             order = c("S2", "S1", "S3", 
                       "E4", "E1", "E5", "E2", "E6", "E3"))
circos.clear()
  • (2)grid间距
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
## 逐一设置
circos.par(gap.after = c(rep(5, nrow(mat)-1), 15, rep(5, ncol(mat)-1), 15))
# circos.par(gap.after = c("S1" = 5, "S2" = 5, "S3" = 15, "E1" = 5, "E2" = 5,
#                          "E3" = 5, "E4" = 5, "E5" = 5, "E6" = 15))
chordDiagram(mat)
circos.clear()

## 分组设置
chordDiagram(mat,
             big.gap = 30,
             small.gap = 5)
circos.clear()
  • (3)grid排列位置

    以sender组的第一个grid的度数为参数,且默认为顺时针

1
2
3
4
circos.par(start.degree = 85, clock.wise = FALSE)
chordDiagram(mat)

circos.clear()
  • (4)grid颜色

    grid的颜色默认每次随机生成

1
2
3
4
5
grid.col = c(S1 = "red", S2 = "green", S3 = "blue",
             E1 = "grey", E2 = "grey", E3 = "grey", E4 = "grey", E5 = "grey", E6 = "grey")
chordDiagram(mat, grid.col = grid.col)

circos.clear()
  • (5)grid宽度设置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
## 宽度保持一致
chordDiagram(mat, grid.col = grid.col, scale = TRUE)

## 两组grid的整体宽度比
df = expand.grid(letters[1:3], LETTERS[1:4])
df$value = 1
df$value2 = 0.5
head(df)
#   Var1 Var2 value value2
# 1    a    A     1    0.5
# 2    b    A     1    0.5
# 3    c    A     1    0.5
# 4    a    B     1    0.5

# chordDiagram(df[, 1:3], grid.col = grid.col)
chordDiagram(df[, 1:4], grid.col = grid.col)
circos.clear()
image-20230116101314341
  • (5)tracks显示

    annotationTrack() 设置显示的tracks

    annotationTrackHeight分别设置name至grid的距离、grid的宽度

1
2
3
4
5
6
7
8
9
chordDiagram(mat, 
             annotationTrack = c("name", "grid","axis"),
             annotationTrackHeight = mm_h(c(5, 5)))
circos.clear()

chordDiagram(mat, 
             annotationTrack = c("name", "grid"),
             annotationTrackHeight = mm_h(c(5, 1))) ## 如下图
circos.clear()
image-20230116092549095
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
chordDiagram(mat,
             transparency = 0.2,
             grid.col = grid.col,
             annotationTrack = "grid", #仅绘制grid层
             preAllocateTracks = 1 #预留一个track用于绘制name层
)
circos.track(track.index = 1, panel.fun = function(x, y) {
  circos.text(CELL_META$xcenter, 
              CELL_META$ylim[1], 
              CELL_META$sector.index,
              facing = "clockwise", 
              niceFacing = TRUE, 
              adj = c(0, 0.5), 
              cex = 1
  )
}, bg.border = NA)
circos.clear()
image-20230116093901325

3、link设置

  • (1)link的颜色

    link的颜色默认

    为sender的grid颜色的50%透明度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
## 透明度
chordDiagram(mat, grid.col = grid.col, transparency = 0.9)

## 自定义颜色
col_mat = rand_color(length(mat), transparency = 0.5)
dim(col_mat) = dim(mat)  # to make sure it is a matrix
chordDiagram(mat, grid.col = grid.col, col = col_mat)

## 颜色映射value
col_fun = colorRamp2(range(mat), c("#FFEEEE", "#FF0000"), 
                     transparency = 0.5)
chordDiagram(mat, grid.col = grid.col, col = col_fun)

circos.clear()

## row.col将link的颜色随sender保持一致
## column.col将link的颜色随receiver保持一致
par(mfrow = c(1,2))
# chordDiagram(mat, grid.col = grid.col, row.col = 1:3)
chordDiagram(mat, grid.col = grid.col, row.col = rainbow(3))
# chordDiagram(mat, grid.col = grid.col, column.col = 1:6)
chordDiagram(mat, grid.col = grid.col, column.col = rainbow(6))
circos.clear()
par(mfrow = c(1,1))
image-20230116095346412
  • (2)link的边框设置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
## 统一设置
chordDiagram(mat, 
             link.lwd = 2, link.lty = 2, link.border = "red")

## 逐一设置
lwd_mat = matrix(1, nrow = nrow(mat), ncol = ncol(mat))
lwd_mat[mat > 12] = 2
border_mat = matrix(NA, nrow = nrow(mat), ncol = ncol(mat))
border_mat[mat > 12] = "red"
chordDiagram(mat, grid.col = grid.col, link.lwd = lwd_mat, link.border = border_mat)

## 单组设置
border_mat2 = matrix("black", nrow = 1, ncol = ncol(mat))
rownames(border_mat2) = rownames(mat)[2]
colnames(border_mat2) = colnames(mat)
#        E1      E2      E3      E4      E5      E6     
# S2 "black" "black" "black" "black" "black" "black"
chordDiagram(mat, grid.col = grid.col, 
             link.lwd = 2, link.border = border_mat2)

## 指定link设置
lty_df = data.frame(c("S1", "S2", "S3"), c("E5", "E6", "E4"), c(1, 2, 3))
lwd_df = data.frame(c("S1", "S2", "S3"), c("E5", "E6", "E4"), c(2, 2, 2))
border_df = data.frame(c("S1", "S2", "S3"), c("E5", "E6", "E4"), c(1, 1, 1))
chordDiagram(mat, grid.col = grid.col, 
             link.lty = lty_df, 
             link.lwd = lwd_df,
             link.border = border_df)
image-20230116095938789
  • (3)link的排序设置
1
2
3
4
5
6
7
8
9
## (1) 按receiver组内升降序排列
chordDiagram(mat, grid.col = grid.col, 
             link.sort = TRUE, link.decreasing = TRUE)
chordDiagram(mat, grid.col = grid.col, 
             link.sort = TRUE, link.decreasing = FALSE)

## (2) 全局link的value排序
chordDiagram(mat, grid.col = grid.col, 
             transparency = 0, link.zindex = rank(mat))
image-20230116100509424
  • (4)link的方向设置
1
2
3
4
5
chordDiagram(mat, grid.col = grid.col, directional = 1) # 正向
chordDiagram(mat, grid.col = grid.col, directional = 1, 
             diffHeight = mm_h(5))
chordDiagram(mat, grid.col = grid.col, directional = -1) # 反向
chordDiagram(mat, grid.col = grid.col, directional = 2) # 双向
image-20230116101728023
1
2
3
4
5
arr.col = data.frame(c("S1", "S2", "S3"), c("E5", "E6", "E4"), 
                     c("black", "black", "black"))
chordDiagram(mat, grid.col = grid.col, directional = 1, 
             direction.type = c("diffHeight", "arrows"),
             link.arr.col = arr.col, link.arr.length = 0.3)
image-20230116101825870
1
2
3
4
5
chordDiagram(mat, directional = 1, 
             direction.type = c("diffHeight", "arrows"),
             link.arr.type = "big.arrow",
             diffHeight = mm_h(5),
             target.prop.height = mm_h(5))
image-20230116101913768