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
<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>
/* 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;
});
});
}