简体   繁体   English

R circlize - 绘制边距和绘制区域

[英]R circlize - plot margins and plotting regions

I'm trying to replicate the graphs of this website https://gjabel.wordpress.com/2014/03/28/circular-migration-flow-plots-in-r/ using the r library "circlize". 我正在尝试使用r库“circlize”复制此网站的图表https://gjabel.wordpress.com/2014/03/28/circular-migration-flow-plots-in-r/ Unfortunately I have two problems: 不幸的是我有两个问题:

First of all I got a warning for all plotting regions (ie Note: 1 point is out of plotting region in sector 'Mexico', track '1' ). 首先,我得到了所有绘图区域的警告(即Note: 1 point is out of plotting region in sector 'Mexico', track '1' )。 I thought the problem was that in circos.text and circos.axis , since I was using them along with direction , which is a deprecated function. 我认为,问题是,在circos.textcircos.axis ,因为我使用它们沿direction ,这是一个过时的功能。 But also using facing instead of direction , the problem persists. 但也使用facing而不是direction ,问题仍然存在。 So I guess I didn't understand the meaning of this warning. 所以我想我不理解这个警告的含义。 Do you have some hints so to help me? 你有一些提示可以帮助我吗?

Moreover, in my plot, links were very far from segments. 而且,在我的情节中,链接距离细分很远。 Thus I tried to reduce the track.margin, which solve the problem, but now the names of the segments are outside the margins, and I cannot visualize them. 因此,我试图减少track.margin,它解决了这个问题,但现在这些段的名称都在边缘之外,我无法将它们可视化。 Is there a better way to solve this problem? 有没有更好的方法来解决这个问题?

This is what I wrote so far (which is almost entirely taken from this site https://github.com/null2/globalmigration ) 这是我到目前为止所写的内容(几乎完全取自本网站https://github.com/null2/globalmigration

library("circlize")
library("plyr")
library("migest")
#load data
m<-read.table(system.file("science", "country_custom.txt", package = "migest"), skip=2, stringsAsFactors=FALSE)
#1)a data.frame to store information on each segment of the circle to be plotted
df1<-m[,1:3]
names(df1)<-c("order","rgb","region")
df1$region<-gsub("\\.", "\n", df1$region)
#2) a matrix containing the flow data (in this example only 28 countries)
m<-m[,-(1:3)]/1e05
m<-as.matrix(m)
dimnames(m)<-list(orig=df1$region,dest=df1$region)
#sort order of data.frame and matrix for plotting in circos    
df1<-arrange(df1, order) #reordering a data frame by its columns
df1$region <- factor(df1$region, levels=df1$region)
m<-m[levels(df1$region),levels(df1$region)]
#define ranges of circos sectors and their colors (both of the sectors and the links)
#determine the length of segments on the outside of the plot.
df1$xmin <- 0
df1$xmax <- rowSums(m)+colSums(m) #inflows+outflows
#set the colour names for segments and flows
n<-nrow(df1)
df1 <- cbind(df1, matrix(as.numeric(unlist(strsplit(df1$rgb,","))),nrow=n, byrow=TRUE) )
names(df1)[ncol(df1)-2:0]<-c("r","g","b")
df1$rcol<-rgb(df1$r, df1$g, df1$b, max = 255)
df1$lcol<-rgb(df1$r, df1$g, df1$b, alpha=200, max = 255)
##plot sectors
windows()
par(mar=rep(0,4))
circos.clear()
#1)basic circos graphic parameters
circos.par(cell.padding=c(0,0,0,0), track.margin=c(0,0.01), start.degree = 90, gap.degree =4)
#2)sector details
circos.initialize(factors = df1$region, xlim = cbind(df1$xmin, df1$xmax))
#3)plot sectors
circos.trackPlotRegion(ylim = c(0, 1), factors = df1$region, track.height=0.1,
       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")

         #text direction (dd) and adjusmtents (aa)
         theta = circlize(mean(xlim), 1.3)[1, 1] %% 360
         dd <- ifelse(theta < 90 || theta > 270, "vertical_right", "vertical_left")
         aa = c(1, 0.5)
         if(theta < 90 || theta > 270)  aa =c(0, 0.5)

         #plot country labels
         circos.text(x=mean(xlim), y=1.7, labels=name, direction = dd,
         cex=0.6,adj = aa)
         #circos.text(x=mean(xlim), y=2, labels=name, facing = "bending",cex=0.6)             

         #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
         #NOTE: Ticks indicate the number of migrants in 100s.
         circos.axis(labels.cex=0.6, direction = "outside", major.at=seq(from=0,to=floor(df1$xmax)[i],by=5), 
         minor.ticks=1, labels.away.percentage = 0.15)
       })

Thank you very much for your help. 非常感谢您的帮助。

EDIT: I add a second part of the script, since it seems that it is necessary to solve the second issue. 编辑:我添加了脚本的第二部分,因为它似乎有必要解决第二个问题。

#plot links
#create a new dataframe containing the long form of the matrix m
#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) #outflows
df1$sum2 <- numeric(n)
#create a data.frame of the flow matrix sorted by flow size, to allow largest flow plotted first
df2<-cbind(as.data.frame(m),orig=rownames(m),  stringsAsFactors=FALSE)
#long matrix
df2<-reshape(df2, idvar="orig", varying=list(1:n), direction="long", timevar="dest", time=rownames(m),  v.names = "m") 
df2<-arrange(df2,desc(m))
#keep only the largest flows to avoid clutter
df2<-subset(df2, m>quantile(m,0.925))
#plot links
for(k in 1:nrow(df2)){
require("circlize")
#i,j reference of flow matrix
#note: you are selecting the states in region1 according to the edgelist in region2
i<-match(df2$orig[k],df1$region)
j<-match(df2$dest[k],df1$region)
#plot link
#sector.index1=sender
#point1=size of the base of the link at the origin
#We set the origin segment to start at the current sum of outflows from the sender country (df1$sum1[i])    
#We set the end of the segment outflow equal to the total outflows from the sender country, plus the flow from the edge we considered
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]) #, top.ratio==0.66, top.ratio.low==0.67)
#note: The height and thickness of the link at its mid-point is determined by the top.ratio and the top.ratio.low argument
#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])
}

You may check chordDiagram() in current version of circlize . 您可以在circlize的当前版本中检查chordDiagram() chordDiagram() is a flexible function which makes such Chord Diagram (ie a circular plot with links inside). chordDiagram()是一个灵活的函数,它可以生成这样的Chord Diagram(即带有链接的圆形图)。 This function was introduced in recent versions of circlize and you don't need too much code to self-define a Chord Diagram. 这个函数是在最新版本的circlize中引入的,你不需要太多的代码来自定义Chord Diagram。 There is also a vignette shipped with the package which gives you detailed introduction of how to make a simple or complex Chord Diagram. 该软件包附带了一个小插图,为您提供如何制作简单或复杂的Chord Diagram的详细介绍。

A quick demonstration of reproducing the figure you are interested is as follows: 快速演示再现您感兴趣的人物如下:

mat = matrix(runif(36), 6)
rownames(mat) = letters[1:6]
colnames(mat) = letters[1:6]

library(circlize)
circos.par(gap.degree = 8)
chordDiagram(mat, grid.col = 1:6, directional = TRUE, annotationTrack = "grid",
  preAllocateTracks = list(list(track.height = 0.05),
                           list(track.height = 0.05)))
circos.trackPlotRegion(track.index = 1, 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, facing = "inside", niceFacing = TRUE)
}, bg.border = NA)
circos.trackPlotRegion(track.index = 2, panel.fun = function(x, y) {
  circos.axis("bottom", major.tick.percentage = 0.2, labels.cex = 0.4)
}, bg.border = NA)
circos.clear()

在此输入图像描述

The first problem concerning the notes messages is not really a problem. 关于笔记消息的第一个问题并不是真正的问题。 You can still get the plot you want regardless of the warning. 无论警告如何,您仍然可以获得所需的情节。 You can subdue the message using 您可以使用制服消息

circos.par(points.overflow.warning=FALSE)

The second problem is a result of a recent update to the circlize package. 第二个问题是最近更新circlize包的结果。 You need to change the track margins from their initial settings by adding 您需要通过添加来更改其初始设置中的轨道边距

circos.par(track.margin=c(0,0)) 

after circos.trackPlotRegion command and before the links are drawn via the circos.link function in the for loop. circos.trackPlotRegion命令之后,在通过for循环中的circos.link函数绘制链接之前。

Sorry for the problems. 抱歉有问题。 I have been meaning to update the demo file in the migest package for a while now but sort of forgot about it over the holidays. 我一直想在migest包中更新演示文件一段时间,但有点忘了假期。

As the author explained here 正如作者在此解释的那样

"points.overflow.warning" Since each cell is in fact not a real plotting region but only an ordinary rectangle, it does not eliminate points that are plotted out of the region. “points.overflow.warning”由于每个单元格实际上不是一个真正的绘图区域,而只是一个普通的矩形,因此它不会消除从该区域绘制的点。 So if some points are out of the plotting region, circlize would continue drawing the points and printing warnings. 因此,如果某些点不在绘图区域内,则circlize将继续绘制点并打印警告。 In some cases, draw something out of the plotting region is useful, such as draw some legend or text. 在某些情况下,从绘图区域绘制一些东西很有用,例如绘制一些图例或文本。 Set this value to FALSE to turn off the warnings. 将此值设置为FALSE以关闭警告。

by canvas.xlim and canvas.ylim (described in the same page above), you can set up your canvas in order to avoid, or just ignore the warning. 通过canvas.xlimcanvas.ylim (在上面的同一页面中描述),您可以设置画布以避免或忽略警告。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM