R make circle/chord diagram with circlize from dataframe

前端 未结 3 1956
无人共我
无人共我 2020-12-07 23:43

I would like to make a chord diagram using the circlize package . I have a dataframe containing cars with four columns. The 2 first columns contains information on car band

3条回答
  •  無奈伤痛
    2020-12-08 00:05

    As I updated the package a little bit, there is now a simpler way to do it. I will give another answer here in case someone is interested with it.

    In the latest several versions of circlize, chordDiagram() accepts both adjacency matrix and adjacency list as input, which means, now you can provide a data frame which contains pairwise relation to the function. Also there is a highlight.sector() function which can highlight or mark more than one sectors at a same time.

    I will implement the plot which I showed before but with shorter code:

    df = read.table(textConnection("
     brand_from model_from brand_to model_to
          VOLVO        s80      BMW  5series
            BMW    3series      BMW  3series
          VOLVO        s60    VOLVO      s60
          VOLVO        s60    VOLVO      s80
            BMW    3series     AUDI       s4
           AUDI         a4      BMW  3series
           AUDI         a5     AUDI       a5
    "), header = TRUE, stringsAsFactors = FALSE)
    
    brand = c(structure(df$brand_from, names=df$model_from),
              structure(df$brand_to,names= df$model_to))
    brand = brand[!duplicated(names(brand))]
    brand = brand[order(brand, names(brand))]
    brand_color = structure(2:4, names = unique(brand))
    model_color = structure(2:8, names = names(brand))
    

    The value for brand, brand_color and model_color are:

    > brand
         a4      a5      s4 3series 5series     s60     s80
     "AUDI"  "AUDI"  "AUDI"   "BMW"   "BMW" "VOLVO" "VOLVO"
    > brand_color
     AUDI   BMW VOLVO
        2     3     4
    > model_color
         a4      a5      s4 3series 5series     s60     s80
          2       3       4       5       6       7       8
    

    This time, we only add one additional track which puts lines and brand names. And also you can find the input variable is actually a data frame (df[, c(2, 4)]).

    library(circlize)
    gap.degree = do.call("c", lapply(table(brand), function(i) c(rep(2, i-1), 8)))
    circos.par(gap.degree = gap.degree)
    
    chordDiagram(df[, c(2, 4)], order = names(brand), grid.col = model_color,
        directional = 1, annotationTrack = "grid", preAllocateTracks = list(
            list(track.height = 0.02))
    )
    

    Same as the before, the model names are added manually:

    circos.trackPlotRegion(track.index = 2, panel.fun = function(x, y) {
        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, col = "white", cex = 0.6, facing = "inside", niceFacing = TRUE)
    }, bg.border = NA)
    

    In the end, we add the lines and the brand names by highlight.sector() function. Here the value of sector.index can be a vector with length more than 1 and the line (or a thin rectangle) will cover all specified sectors. A label will be added in the middle of sectors and the radical position is controlled by text.vjust option.

    for(b in unique(brand)) {
      model = names(brand[brand == b])
      highlight.sector(sector.index = model, track.index = 1, col = brand_color[b], 
        text = b, text.vjust = -1, niceFacing = TRUE)
    }
    
    circos.clear()
    

提交回复
热议问题