Interactive Chord Diagrams

Preamble

In [2]:
:dep chord = {Version = "0.1.4"}
use chord::{Chord, Plot};

Introduction

In a chord diagram (or radial network), entities are arranged radially as segments with their relationships visualised by arcs that connect them. The size of the segments illustrates the numerical proportions, whilst the size of the arc illustrates the significance of the relationships1.

Chord diagrams are useful when trying to convey relationships between different entities, and they can be beautiful and eye-catching.

The Chord Crate

I wasn't able to find any Rust crates for plotting chord diagrams, so I ported my own from Python to Rust.

You can get the package either from crates.io or from the GitHub repository. With your processed data, you should be able to plot something beautiful with just a single line, Chord{ matrix : matrix, names : names, .. Chord::default() }.show()

The Dataset

The focus for this section will be the demonstration of the chord package. To keep it simple, we will use synthetic data that illustrates the co-occurrences between movie genres within the same movie.

In [30]:
let matrix: Vec<Vec<f64>> = vec![
    vec![0., 5., 6., 4., 7., 4.],
    vec![5., 0., 5., 4., 6., 5.],
    vec![6., 5., 0., 4., 5., 5.],
    vec![4., 4., 4., 0., 5., 5.],
    vec![7., 6., 5., 5., 0., 4.],
    vec![4., 5., 5., 5., 4., 0.],
];

let names: Vec<String> = vec![
    "Action",
    "Adventure",
    "Comedy",
    "Drama",
    "Fantasy",
    "Thriller",
]
.into_iter()
.map(String::from)
.collect();

Chord Diagrams

Let's see what the Chord defaults produce when we invoke the show() method.

In [32]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    ..Chord::default()
}
.show();
Out[32]:
Chord Diagram

Different Colours

The defaults are nice, but what if we want different colours? You can pass in almost anything from d3-scale-chromatic, or you could pass in a list of hexadecimal colour codes.

In [33]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: "d3.schemeSet2".to_string(),
    ..Chord::default()
}
.show();
Out[33]:
Chord Diagram
In [34]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: format!("d3.schemeGnBu[{:?}]",names.len()).to_string(),
    ..Chord::default()
}
.show();
Out[34]:
Chord Diagram
In [35]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: "d3.schemeSet3".to_string(),
    ..Chord::default()
}
.show();
Out[35]:
Chord Diagram
In [36]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: format!("d3.schemePuRd[{:?}]",names.len()).to_string(),
    ..Chord::default()
}
.show();
Out[36]:
Chord Diagram
In [37]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: format!("d3.schemeYlGnBu[{:?}]",names.len()).to_string(),
    ..Chord::default()
}
.show();
Out[37]:
Chord Diagram
In [38]:
let hex_colours : Vec<String> = vec!["#222222", "#333333", "#4c4c4c", "#666666", "#848484", "#9a9a9a"].into_iter()
.map(String::from)
.collect();

Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: true,
    colors: format!("{:?}",hex_colours),
    ..Chord::default()
}
.show();
Out[38]:
Chord Diagram

Label Styling

We can disable wrapped labels, and even change the colour.

In [39]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    wrap_labels: false,
    label_color:"#4c40bf".to_string(),
    ..Chord::default()
}
.show();
Out[39]:
Chord Diagram

Opacity

We can also change the default opacity of the relationships.

In [40]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    opacity: 0.1,
    ..Chord::default()
}
.show();
Out[40]:
Chord Diagram

Width

We can also change the maximum width the plot.

In [41]:
Chord {
    matrix: matrix.clone(),
    names: names.clone(),
    width: 400.0,
    wrap_labels: true,
    ..Chord::default()
}
.show()
Out[41]:
Chord Diagram

Conclusion

In this section, we've introduced the chord diagram and chord crate. We used the crate and some synthetic data to demonstrate several chord diagram visualisations with different configurations. The chord Python package is available for free from crates.io or from the GitHub repository.


  1. Tintarev, N., Rostami, S., & Smyth, B. (2018, April). Knowing the unknown: visualising consumption blind-spots in recommender systems. In Proceedings of the 33rd Annual ACM Symposium on Applied Computing (pp. 1396-1399). 

Support this work

You can access this notebook and more by getting the e-book on Data Analysis with Rust Notebooks.