Home | Blog | Software | Publications | GitHub


Multiple-group chord diagram

By default chordDiagram() function in circlize package visualizes relations between two groups (i.e. from rows to columns if the input is an adjacency matrix or from column 1 to column 2 if the input is an adjacency list). However, it is easy to visualize relations among more than 2 groups.

In this post I will demonstrate how to visualize relations from three groups. The example here are matrix as inputs, but the principle should be the same with adjacency data frames.

First let's generate three matrix which contain pairwise relations from three groups:

options(digits = 2)
mat1 = matrix(rnorm(25), nrow = 5)
rownames(mat1) = paste0("A", 1:5)
colnames(mat1) = paste0("B", 1:5)

mat2 = matrix(rnorm(25), nrow = 5)
rownames(mat2) = paste0("A", 1:5)
colnames(mat2) = paste0("C", 1:5)

mat3 = matrix(rnorm(25), nrow = 5)
rownames(mat3) = paste0("B", 1:5)
colnames(mat3) = paste0("C", 1:5)

The key idea here is to merge multiple groups into a single big matrix:

mat = matrix(0, nrow = 10, ncol = 10)
rownames(mat) = c(rownames(mat2), rownames(mat3))
colnames(mat) = c(colnames(mat1), colnames(mat2))
mat[rownames(mat1), colnames(mat1)] = mat1
mat[rownames(mat2), colnames(mat2)] = mat2
mat[rownames(mat3), colnames(mat3)] = mat3
mat
##        B1    B2    B3     B4     B5    C1    C2     C3     C4    C5
## A1  0.919  0.52 -1.02  1.844 -0.071 -2.05 -1.44 -1.602 -1.287 -0.12
## A2 -0.575  0.30  0.12 -0.652  1.445  1.13  0.70 -0.531  0.788 -0.28
## A3  0.608  0.11 -0.95  0.235  0.452 -1.46 -0.26 -1.462  0.769  0.56
## A4 -1.618 -0.64 -0.49  0.078  0.041  0.74 -1.57  0.688  0.332 -0.37
## A5 -0.056 -0.85 -0.26 -0.962 -0.422  1.91 -1.51  2.100 -1.008  0.98
## B1  0.000  0.00  0.00  0.000  0.000 -0.37 -0.42  0.369 -0.741 -0.46
## B2  0.000  0.00  0.00  0.000  0.000  1.05  0.30 -0.215 -1.096 -1.06
## B3  0.000  0.00  0.00  0.000  0.000 -1.05  0.64  0.065  0.038  1.26
## B4  0.000  0.00  0.00  0.000  0.000 -1.26 -0.48 -0.034  0.310 -0.35
## B5  0.000  0.00  0.00  0.000  0.000  3.24  0.52  2.128  0.437 -0.87

When making the chord diagram, it is important to set larger gaps between groups to identify different groups. Here we manually adjust gap.degree in circos.par().

Also we add an additional track in which we add lines to enhance the visual effect of different groups.

library(circlize)
circos.par(gap.degree = rep(c(rep(1, 4), 8), 3))
chordDiagram(mat, annotationTrack = c("grid", "axis"),
    preAllocateTracks = list(
        track.height = 0.08,
        track.margin = c(0.05, 0)
))
circos.track(track.index = 2, panel.fun = function(x, y) {
    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, cex = 0.6, niceFacing = TRUE)
}, bg.border = NA)

# add lines which cross multiple sectors
highlight.sector(rownames(mat1), track.index = 1, col = "red", text = "A", niceFacing = TRUE)
highlight.sector(colnames(mat1), track.index = 1, col = "green", text = "B", niceFacing = TRUE)
highlight.sector(colnames(mat2), track.index = 1, col = "blue", text = "C", niceFacing = TRUE)

plot of chunk unnamed-chunk-3

circos.clear()