This post shows how to build a
circular packing with R and the
ggraph
package, and how to remove the main bubble that
packs all the others.
I personally do not like to display the big circle that surrounds the whole chart (level 0, origin). This circle does not provide any information, and the chart looks better without it in my opinion.
To get rid of it, just specify a color equal to the background color
in the scale_fill_manual()
and
scale_color_manual()
functions. Following the same idea,
you can get rid of as many levels of hierarchy as you like.
# Libraries
library(ggraph)
library(igraph)
library(tidyverse)
library(viridis)
# We need a data frame giving a hierarchical structure. Let's consider the flare dataset:
=flare$edges
edges= flare$vertices
vertices <- graph_from_data_frame( edges, vertices=vertices )
mygraph
# Hide the first level (right)
ggraph(mygraph, layout = 'circlepack', weight=size) +
geom_node_circle(aes(fill = as.factor(depth), color = as.factor(depth) )) +
scale_fill_manual(values=c("0" = "white", "1" = viridis(4)[1], "2" = viridis(4)[2], "3" = viridis(4)[3], "4"=viridis(4)[4])) +
scale_color_manual( values=c("0" = "white", "1" = "black", "2" = "black", "3" = "black", "4"="black") ) +
theme_void() +
theme(legend.position="FALSE")
# Second one: hide 2 first levels
ggraph(mygraph, layout = 'circlepack', weight=size) +
geom_node_circle(aes(fill = as.factor(depth), color = as.factor(depth) )) +
scale_fill_manual(values=c("0" = "white", "1" = "white", "2" = magma(4)[2], "3" = magma(4)[3], "4"=magma(4)[4])) +
scale_color_manual( values=c("0" = "white", "1" = "white", "2" = "black", "3" = "black", "4"="black") ) +
theme_void() +
theme(legend.position="FALSE")
A related problem consists to add labels for one specific level of hierarchy only. For instance, if you want to display the names of group of level2, but not of level 3 to avoid cluttering the chart.
To solve this issue, the trickiest part is to determine the level
of each node in the edge list data frame. Fortunately, the
data.tree
library is here to help with its
FromDataFrameNetwork()
function. It allows to isolate
the level of each node, making it a breeze to select the labels to
display.
# Add the data.tree library
library(data.tree)
# Rebuild the data
<-flare$edges
edges <- flare$vertices
vertices
# Transform it in a 'tree' format
<- FromDataFrameNetwork(edges)
tree
# Then I can easily get the level of each node, and add it to the initial data frame:
<- data.frame( name=tree$Get('name'), level=tree$Get("level") )
mylevels <- vertices %>%
vertices left_join(., mylevels, by=c("name"="name"))
# Now we can add label for level1 and 2 only for example:
<- vertices %>%
vertices mutate(new_label=ifelse(level==2, shortName, NA))
<- graph_from_data_frame( edges, vertices=vertices )
mygraph
# Make the graph
ggraph(mygraph, layout = 'circlepack', weight=size) +
geom_node_circle(aes(fill = as.factor(depth), color = as.factor(depth) )) +
scale_fill_manual(values=c("0" = "white", "1" = viridis(4)[1], "2" = viridis(4)[2], "3" = viridis(4)[3], "4"=viridis(4)[4])) +
scale_color_manual( values=c("0" = "white", "1" = "black", "2" = "black", "3" = "black", "4"="black") ) +
geom_node_label( aes(label=new_label), size=4) +
theme_void() +
theme(legend.position="FALSE", plot.margin = unit(rep(0,4), "cm"))