plot - R make circle/chord diagram with circlize from dataframe -


i make chord diagram using circlize package . have dataframe containing cars 4 columns. 2 first columns contains information on car band , model owned , next 2 columns brand , model respondent migrated to.

here simple example of 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 

it great able make chord diagram. found example in worked i'm not able convert data right format in order make plot. code in circlize package. produces 1 layer, guess need two, brand , 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() 

this code produces following plot:

enter image description here

ideal result example, instead of continents car brand , on inner circle car models belonging brand enter image description here

as updated package little bit, there simpler way it. give answer here in case interested it.

in latest several versions of circlize, chorddiagram() accepts both adjacency matrix , adjacency list input, means, can provide data frame contains pairwise relation function. there highlight.sector() function can highlight or mark more 1 sectors @ same time.

i implement plot showed before 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 brand, brand_color , 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, add 1 additional track puts lines , brand names. , can find input variable 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 before, model names 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 end, add lines , brand names highlight.sector() function. here value of sector.index can vector length more 1 , line (or thin rectangle) cover specified sectors. label added in middle of sectors , radical position controlled 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() 

enter image description here


Comments

Popular posts from this blog

java - Plugin org.apache.maven.plugins:maven-install-plugin:2.4 or one of its dependencies could not be resolved -

Round ImageView Android -

How can I utilize Yahoo Weather API in android -