R从数据框中制作带圆圈的圆/弦图 [英] R make circle/chord diagram with circlize from dataframe

查看:411
本文介绍了R从数据框中制作带圆圈的圆/弦图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用circlize软件包制作一个和弦图.我有一个包含四列汽车的数据框.前两列包含有关所拥有的汽车乐队和车型的信息,后两列包含被调查者迁移到的品牌和车型的信息.

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 and model owned and the next two columns to the brand and model the respondent migrated to.

这是数据框的一个简单示例:

Here is a simple example of the dataframe:

   Brand_from model_from Brand_to Model_to
1:      VOLVO        s80      BMW  5series
2:        BMW    3series      BMW  3series
3:      VOLVO        s60    VOLVO      s60
4:      VOLVO        s60    VOLVO      s80
5:        BMW    3series     AUDI       s4
6:       AUDI         a4      BMW  3series
7:       AUDI         a5     AUDI       a5

能够将其制成和弦图,将是非常不错的.我在帮助中找到了一个有效的示例,但无法将数据转换为正确的格式以进行绘图. 此代码来自circlize软件包中的帮助.这会产生一层,我想我需要两层,品牌和型号.

It would be great to be able to make this into a chord diagram. I found an example in the help that worked but I'm not able to convert my data into the right format in order to make the plot. This code is from the help in the circlize package. This produces one layer, I guess I need two, brand and model.

mat = matrix(1:18, 3, 6)
rownames(mat) = paste0("S", 1:3)
colnames(mat) = paste0("E", 1:6)

rn = rownames(mat)
cn = colnames(mat)
factors = c(rn, cn)
factors = factor(factors, levels = factors)
col_sum = apply(mat, 2, sum)
row_sum = apply(mat, 1, sum)
xlim = cbind(rep(0, length(factors)), c(row_sum, col_sum))

par(mar = c(1, 1, 1, 1))
circos.par(cell.padding = c(0, 0, 0, 0))
circos.initialize(factors = factors, xlim = xlim)
circos.trackPlotRegion(factors = factors, ylim = c(0, 1), bg.border = NA,
                       bg.col = c("red", "green", "blue", rep("grey", 6)), track.height = 0.05,
                       panel.fun = function(x, y) {
                         sector.name = get.cell.meta.data("sector.index")
                         xlim = get.cell.meta.data("xlim")
                         circos.text(mean(xlim), 1.5, sector.name, adj = c(0.5, 0))
})

col = c("#FF000020", "#00FF0020", "#0000FF20")
for(i in seq_len(nrow(mat))) {
  for(j in seq_len(ncol(mat))) {
    circos.link(rn[i], c(sum(mat[i, seq_len(j-1)]), sum(mat[i, seq_len(j)])),
                cn[j], c(sum(mat[seq_len(i-1), j]), sum(mat[seq_len(i), j])),
                col = col[i], border = "white")
  }
}
circos.clear()

此代码生成以下图:

理想的结果将类似于此示例,但我不是大洲,而是汽车品牌,而在内圈上属于该品牌的汽车模型

Ideal result would be like this example, but instead of continents I would like car brand and on the inner circle the car models belonging to the brand

推荐答案

随着我对软件包的更新,现在有了一种更简单的方法.如果有人对此感兴趣,我会在这里给出另一个答案.

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.

在最新的 circlize 版本中,chordDiagram()接受邻接矩阵和邻接列表作为输入,这意味着现在您可以提供一个包含与函数成对关系的数据框.还有一个highlight.sector()功能,可以同时突出显示或标记多个扇区.

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))

brandbrand_colormodel_color的值是:

> 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

这一次,我们仅添加了一条附加曲目,用于放置行和品牌名称.而且您还可以找到输入变量实际上是一个数据帧(df[, c(2, 4)]).

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)

最后,我们通过highlight.sector()函数添加行和品牌名称.在这里,sector.index的值可以是长度大于1的向量,并且线(或细矩形)将覆盖所有指定的扇区.标签将添加到扇区的中间,基本位置由text.vjust选项控制.

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()

这篇关于R从数据框中制作带圆圈的圆/弦图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆