Search code examples
rplotggplot2circle-pack

Grouping plot generated in packcircle function by color groups


I'd like to create a plot similar to this, where each point represents a unique data point of a specific type (eg. red group or blue group), and the points of each group form a circular shape.

circular scatterplot

I have so far gotten this far, using the packcircles function in R:

circular scatterplot attempt

How do I "group" the different colours together? Since I am using the packcircle function, the circle is drawn from the center and then spirals outward, so ordering the points does group them, but I'd rather something more similar to the example I provided above.

Here is the code I used to generate the plot

library(packcircles)
library(ggplot2)
library(plyr)
library(dplyr)

Sample data

data <- data.frame(group=paste("Group", letters[1:4]), value=rep(1,100))
data <- data[order(data$group), ]

Generate layout using packcircles function in R

packing <- circleProgressiveLayout(data$value, sizetype = "area")
id <- data$group
packing <- cbind(id,packing)
dat.gg <- circleLayoutVertices(packing, idcol=1, xysizecols=2:4, npoints=1)

Make the plot using ggplot2

ggplot() + 
geom_point(data = dat.gg, aes(x,y, colour=factor(id))) +
           theme_minimal()  +
           theme(legend.position="none",
                 panel.grid.major=element_blank(),
                 panel.grid.minor=element_blank(),
                 axis.text=element_blank())

Thanks in advance.


Solution

  • I think the way to do it is actually to order your packing along the axis you want before binding it with your data. Doing the same as you but ordering packing along x:

    packing <- circleProgressiveLayout(data$value, sizetype = "area")
    packing <- packing[order(packing$x),]
    id <- data$group
    packing <- cbind(id,packing)
    dat.gg <- circleLayoutVertices(packing, idcol=1, xysizecols=2:4, npoints=1)
    

    I obtain this

    enter image description here

    The initial ordering of packing is with increasing x^2 + y^2, that is distance from the center of your circle. When you bind it you distribute your groups along this ordering of coordinates, that are concentric circles. By changing the ordering you change your distribution on the circle.

    You can of course pack along y, or even you could think of packing along the angle, by calculating it with atan2 function and ordering along the angle before binding:

    packing <- circleProgressiveLayout(data$value, sizetype = "area")
    packing$theta <- atan2(packing$y,packing$x)
    packing <- packing[order(packing$theta),]
    id <- data$group
    packing <- cbind(id,packing)
    dat.gg <- circleLayoutVertices(packing, idcol=1, xysizecols=2:4, npoints=1)
    
    ggplot() + 
      geom_point(data = dat.gg, aes(x,y, colour=factor(id))) +
      theme_minimal()  +
      theme(legend.position="none",
            panel.grid.major=element_blank(),
            panel.grid.minor=element_blank(),
            axis.text=element_blank())
    

    enter image description here