R roundlize - field plots and region plots

I am trying to replicate the graphs of this site https://gjabel.wordpress.com/2014/03/28/circular-migration-flow-plots-in-r/ using the "circlize" r-library. Unfortunately I have two problems:

First of all, I got a warning for all build areas (i.e. 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 used them along with direction

, which is a deprecated feature. But also using facing

instead direction

, the problem persists. Therefore, I think I did not understand the meaning of this warning. Do you have any hints to help me?

Also, in my story, the links were very far from segments. So I tried to reduce track.margin which solved the problem, but now the segment names are out of the margin and I cannot render them. Is there a better way to solve this problem?

This is what I have written so far (which is almost entirely taken from this site 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)
       })

      

Many thanks for your help.

EDIT: I am adding the second part of the script as it seems like the second problem needs to be addressed.

#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])
}

      

+3


source to share


3 answers


The first problem with note messages isn't really a problem. You can still get the plot you want regardless of the warning. You can subordinate the message using

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

      

The second issue is the result of a recent update to the circlize package. You need to change the track fields from their initial settings by adding



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

      

after the command circos.trackPlotRegion

and before the links will be conducted through a function circos.link

in the cycle for

.

Sorry for the problem. I mean updating the demo file in the migest package for a while, but kind of forgot about it during the holidays.

+3


source


You can check chordDiagram()

in the current circlize version . chordDiagram()

is a flexible function that makes a Chord chart like this (i.e. a pie chart with links inside). This function was introduced in recent circlize versions and you don't need too much code to self-define the chord chart. There is also a vignette supplied with the package that gives you a detailed idea of ​​how to make a simple or complex chord chart.

A quick demo of playing the shape you're interested in looks like this:



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

      

enter image description here

+7


source


As the author explained here

"points.overflow.warning" Since each cell is not really a real printable area, but just a regular rectangle, it does not eliminate the dots that are drawn out of the region. Therefore, if some points are missing from the plotting area, it circlize

will continue to draw points and print alerts. In some cases, extracting something from the printable area is useful, for example, to draw some kind of legend or text. Set this value FALSE

to disable warnings.

on canvas.xlim

and canvas.ylim

(described on the same page above), you can customize your canvas to avoid or simply ignore the warning.

+1


source







All Articles