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.
Last active
December 6, 2016 11:39
-
-
Save mbostock/582915 to your computer and use it in GitHub Desktop.
Streamgraph
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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
I have done some hacking and found some flaws in the code. What is the waves() function used for?
Also all the code now is in one script file called stream.js