Skip to content

Instantly share code, notes, and snippets.

@phoebebright
Created August 30, 2012 16:25
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 phoebebright/3532324 to your computer and use it in GitHub Desktop.
Save phoebebright/3532324 to your computer and use it in GitHub Desktop.
Grouped bar

This is a reimplementation of the Grouped Bar Chart by Mike Bostock. Although useful, I found the original's minimal comments and inverted axes hard to follow, so I created the version you see here.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Grouped Bar Chart</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<!-- JS -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.min.js"></script>
<script src="http://d3js.org/d3.v2.js"></script>
<script type="text/javascript" src="main.js"></script>
<script type="text/javascript">
$(document).ready(function () {
main();
});
</script>
</head>
<body>
<div id="vis"></div>
</body>
</html>
function main() {
// This is a reimplementation of the Grouped Bar Chart by Mike Bostock
// (http://bl.ocks.org/882152). Although useful, I found the original's
// minimal comments and inverted axes hard to follow, so I created the
// version you see here.
// First, we define sizes and colours...
var outerW = 640; // outer width
var outerH = 480; // outer height
var padding = { t: 0, r: 0, b: 0, l: 0 };
var w = outerW - padding.l - padding.r; // inner width
var h = outerH - padding.t - padding.b; // inner height
var c = [ "#E41A1C", "#377EB8", "#4DAF4A" ]; // ColorBrewer Set 1
// Second, we define our data...
// Create a two-dimensional array.
// The first dimension has as many Array elements as there are series.
// The second dimension has as many Number elements as there are groups.
// It looks something like this...
// var data = [
// [ 0.10, 0.09, 0.08, 0.07, 0.06, ... ], // series 1
// [ 0.10, 0.09, 0.08, 0.07, 0.06, ... ], // series 2
// [ 0.10, 0.09, 0.08, 0.07, 0.06, ... ] // series 3
// ];
var numberGroups = 10; // groups
var numberSeries = 3; // series in each group
var data = d3.range(numberSeries).map(function () { return d3.range(numberGroups).map(Math.random); });
// Third, we define our scales...
// Groups scale, x axis
var x0 = d3.scale.ordinal()
.domain(d3.range(numberGroups))
.rangeBands([0, w], 0.2);
// Series scale, x axis
// It might help to think of the series scale as a child of the groups scale
var x1 = d3.scale.ordinal()
.domain(d3.range(numberSeries))
.rangeBands([0, x0.rangeBand()]);
// Values scale, y axis
var y = d3.scale.linear()
.domain([0, 1]) // Because Math.random returns numbers between 0 and 1
.range([0, h]);
// Visualisation selection
var vis = d3.select("#vis")
.append("svg:svg")
.attr("width", outerW)
.attr("height", outerH);
// Series selection
// We place each series into its own SVG group element. In other words,
// each SVG group element contains one series (i.e. bars of the same colour).
// It might be helpful to think of each SVG group element as containing one bar chart.
var series = vis.selectAll("g.series")
.data(data)
.enter().append("svg:g")
.attr("class", "series") // Not strictly necessary, but helpful when inspecting the DOM
.attr("fill", function (d, i) { return c[i]; })
.attr("transform", function (d, i) { return "translate(" + x1(i) + ")"; });
// Groups selection
var groups = series.selectAll("rect")
.data(Object) // The second dimension in the two-dimensional data array
.enter().append("svg:rect")
.attr("x", 0)
.attr("y", function (d) { return h - y(d); })
.attr("width", x1.rangeBand())
.attr("height", y)
.attr("transform", function (d, i) { return "translate(" + x0(i) + ")"; });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment