# Customize Hierarchical Edge Bundling

This post shows a few customization you can apply to a hierarchical edge bundling chart. It shows how to control the way connection are curved, how to manage connection colors and node features.

# Basic hierarchical edge bundling

It considers you understood what inputs you need and how to build a basic version. It aims to describe how we can improve it, customizing tension, connection and node features.

First, let’s remember the R code allowing to get this very basic hierarchical edge bundling: ``````# Libraries
library(ggraph)
library(igraph)
library(tidyverse)

# create a data frame giving the hierarchical structure of your individuals
set.seed(1234)
d1 <- data.frame(from="origin", to=paste("group", seq(1,10), sep=""))
d2 <- data.frame(from=rep(d1\$to, each=10), to=paste("subgroup", seq(1,100), sep="_"))
hierarchy <- rbind(d1, d2)

# create a dataframe with connection between leaves (individuals)
all_leaves <- paste("subgroup", seq(1,100), sep="_")
connect <- rbind(
data.frame( from=sample(all_leaves, 100, replace=T) , to=sample(all_leaves, 100, replace=T)),
data.frame( from=sample(head(all_leaves), 30, replace=T) , to=sample( tail(all_leaves), 30, replace=T)),
data.frame( from=sample(all_leaves[25:30], 30, replace=T) , to=sample( all_leaves[55:60], 30, replace=T)),
data.frame( from=sample(all_leaves[75:80], 30, replace=T) , to=sample( all_leaves[55:60], 30, replace=T)) )
connect\$value <- runif(nrow(connect))

# create a vertices data.frame. One line per object of our hierarchy
vertices  <-  data.frame(
name = unique(c(as.character(hierarchy\$from), as.character(hierarchy\$to))) ,
value = runif(111)
)
# Let's add a column with the group of each name. It will be useful later to color points
vertices\$group  <-  hierarchy\$from[ match( vertices\$name, hierarchy\$to ) ]

# Create a graph object
mygraph <- graph_from_data_frame( hierarchy, vertices=vertices )

# The connection object must refer to the ids of the leaves:
from  <-  match( connect\$from, vertices\$name)
to  <-  match( connect\$to, vertices\$name)

# Basic graph
ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
geom_conn_bundle(data = get_con(from = from, to = to), alpha=0.2, colour="skyblue", tension = .5) +
geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05)) +
theme_void()``````

# Playing with `tension`

The first thing we can play with is the `tension` of the connections. A tension of 0 means straight lines. A connection of 1 means maximal curvature: the connections follow the hierarchical structure of the network as much as they can.

Let’s have a look to the effect of different values.

``````p <- ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05)) +
theme_void()

# 0.1
p +  geom_conn_bundle(data = get_con(from = from, to = to), alpha=0.2, colour="skyblue", width=0.9,
tension=0.1)
# 0.7
p +  geom_conn_bundle(data = get_con(from = from, to = to), alpha=0.2, colour="skyblue", width=0.9,
tension=0.7)
#1
p +  geom_conn_bundle(data = get_con(from = from, to = to), alpha=0.2, colour="skyblue", width=0.9,
tension=1) `````` # Connection features

Then we can play with the colour and transparency of connections. We have seen how to pick up a unique color in the example above. We can also map a specific variable to it like we are used to do with ggplot2 (chart 1 and 2 below)! Another possibility is to make the color evolves along the trajectory: the ‘from’ and the ‘to’ have different color. This is useful if your connection is directed, and gives the nice effect figure 4.

``````# Use the 'value' column of the connection data frame for the color:
p +  geom_conn_bundle(data = get_con(from = from, to = to), aes(colour=value, alpha=value))

# In this case you can change the color palette
p +
geom_conn_bundle(data = get_con(from = from, to = to), aes(colour=value)) +
scale_edge_color_continuous(low="white", high="red")
p +
geom_conn_bundle(data = get_con(from = from, to = to), aes(colour=value)) +
scale_edge_colour_distiller(palette = "BuPu")

# Color depends of the index: the from and the to are different
p +
geom_conn_bundle(data = get_con(from = from, to = to), width=1, alpha=0.2, aes(colour=..index..)) +
scale_edge_colour_distiller(palette = "RdPu") +
theme(legend.position = "none")`````` # Node features

Finally we can custom the points as well, like for a classic ggplot2 graphic. It is a good practice to make the color depends of the classification of the point, it allows to make the hierarchy more obvious. In the last example, I map a column to the size of the points!

``````# Basic usual argument
p=ggraph(mygraph, layout = 'dendrogram', circular = TRUE) +
geom_conn_bundle(data = get_con(from = from, to = to), width=1, alpha=0.2, aes(colour=..index..)) +
scale_edge_colour_distiller(palette = "RdPu") +
theme_void() +
theme(legend.position = "none")

# just a blue uniform color. Note that the x*1.05 allows to make a space between the points and the connection ends
p + geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05), colour="skyblue", alpha=0.3, size=3)

# It is good to color the points following their group appartenance
library(RColorBrewer)
p + geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, colour=group),   size=3) +
scale_colour_manual(values= rep( brewer.pal(9,"Paired") , 30))

# And you can adjust the size to whatever variable quite easily!
p +
geom_node_point(aes(filter = leaf, x = x*1.05, y=y*1.05, colour=group, size=value, alpha=0.2)) +
scale_colour_manual(values= rep( brewer.pal(9,"Paired") , 30)) +
scale_size_continuous( range = c(0.1,10) ) `````` Related chart types

## Contact

This document is a work by Yan Holtz. Any feedback is highly encouraged. You can fill an issue on Github, drop me a message on Twitter, or send an email pasting yan.holtz.data with gmail.com.
{"ft_lang_label":"__label__en","ft_lang_prob":0.69507754,"math_prob":0.99272215,"size":5502,"snap":"2023-40-2023-50","text_gpt3_token_len":1537,"char_repetition_ratio":0.11422335,"word_repetition_ratio":0.17290322,"special_character_ratio":0.30225372,"punctuation_ratio":0.18215613,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9973657,"pos_list":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],"im_url_duplicate_count":[null,2,null,2,null,2,null,2,null,2,null,2,null,2,null,2,null,2,null,2,null,2,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-09-22T07:22:23Z\",\"WARC-Record-ID\":\"<urn:uuid:12ac98b3-dd2d-4c7d-8898-9814c1c206ec>\",\"Content-Length\":\"39111\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:214461fa-73e4-44bb-93cd-8510a47b2410>\",\"WARC-Concurrent-To\":\"<urn:uuid:9303251d-736e-427f-b99c-69a5ccd5a9f3>\",\"WARC-IP-Address\":\"185.199.110.153\",\"WARC-Target-URI\":\"https://r-graph-gallery.com/310-custom-hierarchical-edge-bundling.html\",\"WARC-Payload-Digest\":\"sha1:ASLGGI7YMPQUEUBIOF2CEBJUWKJYJBDP\",\"WARC-Block-Digest\":\"sha1:3D5FB7BGA6CYWCUM5232MB4FTNVDO6GH\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-40/CC-MAIN-2023-40_segments_1695233506339.10_warc_CC-MAIN-20230922070214-20230922100214-00445.warc.gz\"}"}