Skip to content

Instantly share code, notes, and snippets.

@jimpick
Forked from mbostock/.block
Created June 1, 2011 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jimpick/1003045 to your computer and use it in GitHub Desktop.
Save jimpick/1003045 to your computer and use it in GitHub Desktop.
Streamgraph

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.

<html>
<head>
<title>Streamgraph</title>
<script type="text/javascript" src="http://vis.stanford.edu/protovis/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;
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment