WeightedTreemaps
Create Voronoi and Sunburst Treemaps from Hierarchical data
Install / Use
/learn @m-jahn/WeightedTreemapsREADME
WeightedTreemaps
Michael Jahn, David Leslie, Ahmadou Dicko, Paul Murrell 2024-11-20
<!-- include logo--> <img src="images/logo.png" align="right" /> <!-- badges start --> <!-- badges end -->Generate and plot Voronoi treemaps or Sunburst treemaps from hierarchical data.
<img src="images/fig_example-1.png" width="50%" style="display: block; margin: auto;" />News
14 December 2023
The package was finally released on CRAN! Prerequisite was testing and
troubleshooting of C++ related compilation problems, and re-release of
the CGAL dependency package RcppCGAL with latest version.
25 March 2021
A Shiny app for generating treemaps from custom data is now available on Shinyapps.io!
Description
Treemaps are a visually appealing graphical representation of numerical data using a space-filling approach. A plane or ‘map’ is subdivided into smaller areas called cells. The cells in the map are scaled according to an underlying metric which allows to grasp the hierarchical organization and relative importance of many objects at once. This package contains two different implementations of treemaps, Voronoi treemaps and Sunburst treemaps
There are different implementations available for Voronoi
tesselations in R, the simplest being the deldir() function (from
package deldir). However, deldir and others do not handle nested
Voronoi tesselations, nor do they perform additively weighted Voronoi
tesselation. This is an important demand for systems biology and other
applications where it is useful to scale the cell size (or area) to a
set of predefined weights. The voronoiTreemap() function provided in
this packages allows both the additively weighted Voronoi tesselation
and the nesting of different hierarchical levels in one plot.
Some of the underlying functions for the tesselation were developed by
Paul Murrell, University of Auckland, and serve as the basis for this
package. They are called by a recursive wrapper function,
voronoiTreemap(), which subdivides the plot area in polygonal cells
according to the highest hierarchical level. It then continues with the
tesselation on the next lower level using the child cell of the previous
level as the new parental cell, and so on.
The Sunburst treemap is a computationally less demanding treemap
that does not require iterative refinement, but simply generates circle
sectors that are sized according to predefined weights. The main
function to draw Sunburst treemaps is sunburstTreemap(). It uses the
same underlying recursive algorithm under the hood and can be used to
draw sectors of different hierarchical levels with increasing
granularity.
Requirements
The C++ code computing the actual Voronoi tesselation requires the
CGAL library headers. Thanks to
Ahmadou Dicko, installing the complete CGAL
library locally is no longer necessary. Instead, the package depends on
the CGAL headers that are available as R packages on CRAN. The package
was using CGAL 4 (package cgal4h), but now moved to the latest CGAL
5.5+ version available as package RcppCGAL. The dependencies are
usually installed automatically and manual installation of CGAL
(headers) should not be necessary.
Note: If the RcppCGAL package is temporarily not available on CRAN (as
happened 2023), please install it manually from
Github.
Installation
To install the package from CRAN, use:
install.packages("WeightedTreemaps")
To install the package directly from github, use the following function
from the devtools package:
devtools::install_github("m-jahn/WeightedTreemaps")
Usage
Voronoi treemaps
The functions to create Voronoi (or Sunburst) treemaps take a
data.frame as main input. The data.frame should contain column(s)
with numerical or categorical data (i.e. a character vector). Let’s
create a simple example data frame.
library(WeightedTreemaps)
# load example data
data(mtcars)
mtcars$car_name = gsub(" ", "\n", row.names(mtcars))
Generate the treemap. It will return a list of polygons and metadata. The columns of the data frame that are used as levels of the treemap need to be specified. Different parameters like the initial shape, or the maximum number of iterations are optional.
# generate treemap; set seed to obtain same pattern every time
tm <- voronoiTreemap(
data = mtcars,
levels = c("gear", "car_name"),
cell_size = "wt",
shape = "rounded_rect",
seed = 123
)
Draw the treemap.
drawTreemap(tm, label_size = 2.5, label_color = "white")
<img src="images/fig_cars_basic-1.png" width="50%" style="display: block; margin: auto;" />
Drawing options
The voronoiTreemap() and drawTreemap() functions are separated in
order to allow drawing of the same treemap object in different ways.
Computation of treemaps with thousands of cells can be very time and
resource consuming (around 5-10 minutes for a 2000-cell treemap on a
regular desktop computer). With the drawTreemap() function, we can not
only plot the same treemap in different ways but also combine several
treemaps on one page using the layout and position arguments. The
most important style element is color. Coloring can be based on cell
category, cell size, or both, using the color_type argument. By
default, the highest hierarchical level is used for coloring but that
can be customized using the color_level argument.
drawTreemap(tm, title = "treemap 1", label_size = 2,
color_type = "categorical", color_level = 1,
layout = c(2, 2), position = c(1, 1), legend = TRUE)
drawTreemap(tm, title = "treemap 2", label_size = 2,
color_type = "categorical", color_level = 2, border_size = 3,
add = TRUE, layout = c(2, 2), position = c(1, 2), legend = TRUE)
drawTreemap(tm, title = "treemap 3", label_size = 2,
color_type = "both", color_level = 1,
add = TRUE, layout = c(2, 2), position = c(2, 1), legend = TRUE)
drawTreemap(tm, title = "treemap 4", label_size = 2,
color_type = "cell_size", color_level = 2,
color_palette = heat.colors(10),
border_color = grey(0.4), label_color = grey(0.4),
add = TRUE, layout = c(2, 2), position = c(2, 2),
title_color = "black", legend = TRUE)
<img src="images/fig_cars_colors-1.png" width="100%" style="display: block; margin: auto;" />
Convergence time
The expansion of cells towards a certain target size is a
non-deterministic process. During each iteration, cell size is adjusted
using weights, but the final result can only be measured after a cell
(polygon) was created. Is it too small compared to the target area, it
will get a higher weight for the next iteration, and vice versa. The
adjustment of weights can be controlled by the convergence parameter
(“slow”, “intermediate”, “fast”). Faster convergence will adjust weights
more strongly and attempts to reach the target size with fewer
iterations. However this procedure increases the probability of
obtaining problematic polygons with for example self-intersections or
holes. Compare the following treemaps generated with identical input
except for the convergence.
convergence <- c("slow", "intermediate", "fast")
for (i in 1:3) {
tm <- voronoiTreemap(
data = mtcars,
levels = c("gear", "car_name"),
cell_size = "wt",
shape = "rounded_rect",
seed = 123,
convergence = convergence[i],
verbose = TRUE
)
drawTreemap(
tm,
title = paste0("convergence = ", convergence[i]),
label_size = 2.5,
label_color = "white",
layout = c(1, 3),
position = c(1, i),
add = ifelse(i == 1, FALSE, TRUE)
)
}
#> Level 1 tesselation: 6.87 % mean error, 10.3 % max error, 100 iterations.
#> Level 2 tesselation: 0.33 % mean error, 0.97 % max error, 63 iterations.
#> Level 2 tesselation: 0.58 % mean error, 0.98 % max error, 48 iterations.
#> Level 2 tesselation: 0.54 % mean error, 0.98 % max error, 71 iterations.
#> Treemap successfully created.
#> Level 1 tesselation: 3.15 % mean error, 4.73 % max error, 100 iterations.
#> Level 2 tesselation: 0.25 % mean error, 0.96 % max error, 71 iterations.
#> Level 2 tesselation: 0.45 % mean error, 0.98 % max error, 52 iterations.
#> Level 2 tesselation: 0.56 % mean error, 0.95 % max error, 64 iterations.
#> Treemap successfully created.
#> Level 1 tesselation: 0.64 % mean error, 0.96 % max error, 97 iterations.
#> Level 2 tesselation: 0.36 % mean error, 0.97 % max error, 93 iterations.
#> Level 2 tesselation: 0.45 % mean error, 1 % max error, 57 iterations.
#> Level 2 tesselation: 0.54 % mean error, 0.98 % max error, 70 iterations.
#> Treemap successfully created.
<img src="images/fig_cars_conv-1.png" width="100%" style="display: block; margin: auto;" />
Positioning of cells
Generating a Voronoi treemap is an iterative and somewhat random process. Since the cells ‘move’ during the iteration process, it can be difficult to control the exact final position of cells. However, there are two ways to influence cell positioning. The first is to use different algorithms for sampling initial coordinates for each cell. The second is sim
