TP

Composable data visualizations

Tomas Petricek

Journal of Functional Programming, vol. 31, 2021

When visualizing data, you have to choose between high-level data visualization libraries such as Google Charts or low-level libraries like D3. In high-level libraries, you specify the type of chart you want, but you are limited to the features that the author of the library implemented. With low-level libraries, you have full control over the look of the chart, but you have to tediously transform your values to coordinates in pixels yourself.

What would an elegant functional approach to data visualization look like? A functional programmer would want a domain-specific language that has a small number of primitives that allow us to define high level abstractions such as a bar chart, but does not limit what we can do. When creating charts, we should be able to use domain values such as a currency exchange rate, rather than pixels in its basic building blocks.

As is often the case with domain-specific languages, finding the right primitives is more of an art than science. For this reason, we present our solution, a library named Compost, as a functional pearl. We hope to convince the reader that Compost is elegant and we illustrate this with a wide range of examples

Paper and more information

Sample chart

The following brief example, from the project homepage shows how to use the Compost JavaScript API to create a chart that combines a line chart, showing the GBP-USD exchange rate, with a two-part background distinguishing the time before the Brexit vote and after the Brexit vote.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
// Exchange rate range for the background
let lo = 1.25, hi = 1.52;
// Overlay three shapes and add axes on three sides
let xchg = c.axes("left right bottom", c.overlay([
  // Fill area behind first 16 values in blue
  c.fillColor("#1F77B460",  c.shape(
    [ [0,lo], [16,lo], [16,hi], [0,hi] ])),
  // Fill area behind the remaining values in red
  c.fillColor("#D6272860",  c.shape(
    [ [gbpusd.length-1,lo], [16,lo], [16,hi], [gbpusd.length-1,hi] ])),
  // Draw a black line using 'gbpusd' array
  c.strokeColor("#202020", c.line(gbpusd.map((v, i) => [i, v])))
]));
// Render chart on <div id="demo" />
c.render("demo", xchg);

Talk recording

Watch a short video presentation associated with the JFP paper:

Bibtex

If you want to cite the paper, you can use the following BibTeX information.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
@article{compost-jfp2021,
  author={Petricek, Tomas},
  title={Composable data visualizations},
  volume={31},
  doi={10.1017/S0956796821000046},
  journal={Journal of Functional Programming},
  publisher={Cambridge University Press},
  year={2021},
}

If you have any comments, suggestions or related ideas, I'll be happy to hear from you! Send me an email at tomas@tomasp.net or get in touch via Twitter at @tomaspetricek.

val lo : float * bool
val xchg : obj

Published: Thursday, 17 June 2021, 12:00 AM
Author: Tomas Petricek
Typos: Send me a pull request!