R Circlize Обнаружить, что некоторые промежутки слишком велики

Я хотел бы сделать аналогичный график, размещенный здесь, однако, используя наши данные, я получил это сообщение об ошибке «Обнаружено, что некоторые промежутки слишком велики». Как вы думаете, потому что некоторые значения очень малы по сравнению с другими (например, 1 против 1812)? Я внес несколько изменений в свои данные, как в матрице 2, добавив несколько нулей после 1 или 2, и это работает. Есть ли способ обойти этот диапазон данных? Я хотел бы построить этот красивый график, используя мои реальные данные (матрица 1). Любая помощь горячо приветствуется.

library(circlize)
#matrix 1
#level0 <- c(1, 8, 39, 14, 2)
#level1 <- c(1, 19, 153, 93, 1)
#level2 <- c(2, 19, 274, 46, 13)
#level3 <- c(0, 8, 152, 1812, 465)
#level4 <- c(0, 2, 1, 164, 226)

#matrix 2
#level0 <- c(100,8,39,14,200)
#level1 <- c(100,190, 153,93,100)
#level2 <- c(200,19,274,646,130)
#level3 <- c(200,800,152,1812,465)
#level4 <- c(200,200,100,164,226)

#build matrix 2
a <- list(c(100,8,39,14,200),c(100,19, 153,93,100), c(200,19,274,646,13),    c(200,8,152,1812,465),c(200,200,100,164,226))
mat <- do.call(rbind, a)
#mat = matrix(sample(1:100, 25, replace = TRUE), 5, 5)
rownames(mat) = c("level 0", "level 1", "level 2", "level 3", "level 4")
colnames(mat) = c("Level0", "Level1", "Level2", "Level3", "Level4")
rn = rownames(mat)
cn = colnames(mat)

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

par(mar = c(1, 1, 1, 1))
circos.par(cell.padding = c(0, 0, 0, 0), clock.wise = FALSE, track.margin=c(0,0.1),
           gap.degree = 4, start.degree =90)
circos.initialize(factors = factors, xlim = xlim
                  , sector.width = c(row_sum/sum(row_sum), col_sum/sum(col_sum)))
circos.trackPlotRegion(factors = factors, ylim = c(0, 1), bg.border = NA,
                       # bg.col = c("red", "orange", "yellow", "green", "blue", rep("grey", 5)), track.height = 0.05,
                       bg.col = c(c("red", "orange", "yellow", "green", "blue"),
                                  c("blue", "green", "yellow", "orange", "red")), 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), 3, sector.name, adj = c(0.5, 0))
                         circos.axis(labels.cex=0.8, direction="outside", labels.away.percentage=0.5)
                         if(sector.name %in% rn) {
                           for(i in seq_len(ncol(mat))) {
                             circos.lines(rep(sum(mat[sector.name, seq_len(i)]), 2), c(0, 1),
                                          col = "white")
                           }
                         } else if(sector.name %in% cn) {
                           for(i in seq_len(nrow(mat))) {
                             circos.lines(rep(sum(mat[ seq_len(i), sector.name]), 2), c(0, 1),
                                          col = "white")
                           }
                         }
                       })
col = c("#FF000020", "#FFA50020", "#FFFF0020", "#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")
  }
}

person Anthony    schedule 28.05.2014    source источник
comment
вы также можете получить график из своего кода, если изменить gap.степень=0.1   -  person guyabel    schedule 28.05.2014


Ответы (2)


Поэтому я думаю, что ваш объект df1 немного отличается от моего исходного кода. Если вы настроите матрицы m и df1 как таковые...

m <- matrix(c(1, 8, 39, 14, 2, 
              1, 19, 153, 93, 1,
              2, 19, 274, 46, 13,
              0, 8, 152, 1812, 465,
              0, 2, 1, 164, 226), nrow=5, byrow=TRUE)
df1 <- data.frame(order=1:5, region=paste0("level",1:5), 
              rcol = c("red", "orange", "yellow", "green", "blue"),
              lcol = c("#FF000020", "#FFA50020", "#FFFF0020", "#00FF0020", "#0000FF20"),
              stringsAsFactors=FALSE)
df1$region <- factor(df1$region, levels=df1$region)
df1$xmin <- 0
df1$xmax <- rowSums(m)+colSums(m)
n <-nrow(df1)

dimnames(m) <- list(orig=df1$region,dest=df1$region)

Вы получаете следующие объекты...

> df1
  order region   rcol      lcol xmin xmax
1     1 level1    red #FF000020    0   68
2     2 level2 orange #FFA50020    0  323
3     3 level3 yellow #FFFF0020    0  973
4     4 level4  green #00FF0020    0 4566
5     5 level5   blue #0000FF20    0 1100
> addmargins(m)
        dest
orig     level1 level2 level3 level4 level5  Sum
  level1      1      8     39     14      2   64
  level2      1     19    153     93      1  267
  level3      2     19    274     46     13  354
  level4      0      8    152   1812    465 2437
  level5      0      2      1    164    226  393
  Sum         4     56    619   2129    707 3515

Я более подробно объясняю цель df1 в рабочий документ. Вкратце, объект df1 содержит информацию о длинах секторов для построения (xmin и xmax) и цветах круглых прямоугольников снаружи rcol и цветах ленточных связей lcol. Конечно, вы могли бы иметь те же самые lcol и rcol,... адаптироваться, пока не получите палитру/стиль, который вам нравится (возможно, немного меньшую прозрачность для lcol).

Затем вы можете продолжить и использовать код, очень похожий на тот, что у меня есть в демонстрационном файле в migest package, чтобы получить график (я изменил только аргументы оси circos.axis и подмножество df2)...

library(circlize)
library(plyr)
par(mar=rep(0,4))
circos.clear()

#basic circos graphic parameters
circos.par(cell.padding=c(0,0,0,0), track.margin=c(0,0.15), start.degree = 90, gap.degree =4)

#sector details
circos.initialize(factors = df1$region, xlim = cbind(df1$xmin, df1$xmax))

#plot sectors
circos.trackPlotRegion(ylim = c(0, 1), factors = df1$region, track.height=0.1,
 #panel.fun for each sector
 panel.fun = function(x, y) {
   #select details of current sector
   name = get.cell.meta.data("sector.index")
   i = get.cell.meta.data("sector.numeric.index")
   xlim = get.cell.meta.data("xlim")
   ylim = get.cell.meta.data("ylim")

   #plot labels
   circos.text(x=mean(xlim), y=2.2, labels=name, facing = "arc", cex=0.8)

   #plot main sector
   circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2], ytop=ylim[2], col = df1$rcol[i], border=df1$rcol[i])

   #blank in part of main sector
   #circos.rect(xleft=xlim[1], ybottom=ylim[1], xright=xlim[2]-rowSums(m)[i], ytop=ylim[1]+0.3, col = "white", border = "white")

   #white line all the way around
   #circos.rect(xleft=xlim[1], ybottom=0.3, xright=xlim[2], ytop=0.32, col = "white", border = "white")

   #plot axis
   circos.axis(labels.cex=0.6, major.at=seq(from=0,to=floor(df1$xmax)[i],by=500), 
                                 labels.away.percentage = 0.15)
})

##
##plot links
##
#add sum values to df1, marking the x-position of the first links out (sum1) and in (sum2). Updated for further links in loop below.
df1$sum1 <- colSums(m)
df1$sum2 <- numeric(n)

#create a data.frame of matrix sorted by element size, to allow largest plotted first
df2 <- cbind(as.data.frame(m),orig=rownames(m),  stringsAsFactors=FALSE)
df2 <- reshape(df2, idvar="orig", varying=list(1:n), direction="long", timevar="dest", time=rownames(m),  v.names = "m")
df2 <- arrange(df2,desc(m))

#loose non zero links
df2 <- subset(df2, m>0)

#plot links
for(k in 1:nrow(df2)){
  #i,j reference of flow matrix
  i<-match(df2$orig[k],df1$region)
  j<-match(df2$dest[k],df1$region)

  #plot link
  circos.link(sector.index1=df1$region[i], point1=c(df1$sum1[i], df1$sum1[i] + abs(m[i, j])),
          sector.index2=df1$region[j], point2=c(df1$sum2[j], df1$sum2[j] + abs(m[i, j])),
          col = df1$lcol[i])

  #update sum1 and sum2 for use when plotting the next link
  df1$sum1[i] = df1$sum1[i] + abs(m[i, j])
  df1$sum2[j] = df1$sum2[j] + abs(m[i, j])
}

Что дает такой сюжет...

введите здесь описание изображения

Если вы хотите добавить графику некоторую направленность, раскомментируйте две строки в panel.fun, которые добавляют белые прямоугольники и линию границы.

person guyabel    schedule 28.05.2014
comment
На самом деле я хотел поток в одном направлении, и он не позволяет использовать одно и то же имя как для строки, так и для столбца. Я тоже хотел воспроизвести приведенный выше график, но он у меня работает. Я скопировал и вставил ваши коды и как-то не то. Вы изменили другие параметры, кроме circos.asis и df2. Спасибо за всю вашу помощь Гай. - person Anthony; 28.05.2014
comment
Я думаю, что это выглядит лучше с вашим графиком. Вместо того, чтобы рисовать ленты одинаковых уровней через цирк, мы можем нанести их на каждый уровень. - person Anthony; 29.05.2014
comment
@Энтони Плохо, у меня был аргумент top, а не ytop в первом аргументе circos.rect. Должно работать сейчас? Я также закомментировал белые прямоугольники, которые перекрывали цветные прямоугольники... чтобы избавиться от направленности. - person guyabel; 29.05.2014
comment
Это замечательно. Я только что воспроизвел ваш график, и он выглядит потрясающе. В очередной раз благодарим за помощь. - person Anthony; 29.05.2014
comment
@gjabel - Спасибо за это. Быстрые заметки ... кажется, что для circos.text аргумент «направление» обесценивается - вместо этого нужно использовать «обращение». Кроме того, я попытался запустить этот код целиком и получил следующую ошибку: Ошибка в circos.link(sector.index1 = df1$region[i], point1 = c(df1$sum1[i], : unused arguments (top. ratio=0.66, top.ratio.low=0.67) - это тоже что-то изменилось с обновленной версией circlize?или ошибка только у меня? - person jalapic; 21.07.2014
comment
@japapic Спасибо за место. Ошибка у вас тоже из нового обновления (top.ratio и top.ratio.low вроде ушли, заменены на h и h2). Теперь по умолчанию ссылки выглядят очень похоже на те, что на графике выше, поэтому, по крайней мере, в приведенном выше случае нет необходимости указывать h и h2. Я изменил код в ответе, чтобы он соответствовал обновленному пакету circlize. Теперь должно работать без ошибок. - person guyabel; 21.07.2014
comment
@gjabel спасибо - еще одна вещь. По-видимому, «облицовка» не может принимать «дугу» в качестве опции. Я получаю сообщение об ошибке, подобное этому: 'arg' должен быть одним из "внутри", "снаружи", "наоборот по часовой стрелке", "по часовой стрелке", "вниз", "изгиб" ..... с использованием любого из этих хотя работает. - person jalapic; 21.07.2014

Большой! Вот что я сделал, чтобы получить следующий график: - изменил зазор.степень=0,1 - преобразовал числа в проценты (мат‹-мат/4700*100) - удалил rev() в множителях

введите здесь описание изображения

person Anthony    schedule 28.05.2014