A graphical toolkit for visualization
Protovis
Overview
Examples
Documentation
Download
Index
« Previous / Next »

Streamgraphs

View full screen.

Streamgraphs are a generalization of stacked area graphs where the baseline is free. By shifting the baseline, it is possible to minimize the change in slope (or “wiggle”) in individual series, thereby making it easier to perceive the thickness of any given layer across the data. Byron & Wattenberg describe several streamgraph algorithms in “Stacked Graphs—Geometry & Aesthetics”, several of which are implemented by pv.Layout.Stack. As additional examples, see stacked graphs of employment and unemployment statistics.

Next: Sparklines

Source

<html>
  <head>
    <title>Streamgraph</title>
    <script type="text/javascript" src="../protovis-r3.2.js"></script>
    <script type="text/javascript" src="stream.js"></script>
    <style type="text/css">

body {
  margin: 0;
}

    </style>
  </head>
  <body>
    <script type="text/javascript+protovis">

var n = 20, // number of layers
    m = 400, // number of samples per layer
    data = layers(n, m);

var w = document.body.clientWidth,
    h = document.body.clientHeight,
    x = pv.Scale.linear(0, m - 1).range(0, w),
    y = pv.Scale.linear(0, 2 * n).range(0, h);

var vis = new pv.Panel()
    .width(w)
    .height(h);

vis.add(pv.Layout.Stack)
    .layers(data)
    .order("inside-out")
    .offset("wiggle")
    .x(x.by(pv.index))
    .y(y)
  .layer.add(pv.Area)
    .fillStyle(pv.ramp("#aad", "#556").by(Math.random))
    .strokeStyle(function() this.fillStyle().alpha(.5));

vis.render();

    </script>
  </body>
</html>

Data

/* Inspired by Lee Byron's test data generator. */
function layers(n, m) {
  function bump(a) {
    var x = 1 / (.1 + Math.random()),
        y = 2 * Math.random() - .5,
        z = 10 / (.1 + Math.random());
    for (var i = 0; i < m; i++) {
      var w = (i / m - y) * z;
      a[i] += x * Math.exp(-w * w);
    }
  }
  return pv.range(n).map(function() {
      var a = [], i;
      for (i = 0; i < m; i++) a[i] = 0;
      for (i = 0; i < 5; i++) bump(a);
      return a;
    });
}

/* Another layer generator using gamma distributions. */
function waves(n, m) {
  return pv.range(n).map(function(i) {
    return pv.range(m).map(function(j) {
        var x = 20 * j / m - i / 3;
        return x > 0 ? 2 * x * Math.exp(-.5 * x) : 0;
      });
    });
}
Copyright 2010 Stanford Visualization Group