Last active
July 26, 2016 21:19
-
-
Save tianhuil/7936887 to your computer and use it in GitHub Desktop.
Grouped Horizontal Bar Graph in d3. This is simply reversing the x and y axes of http://bl.ocks.org/mbostock/3887051
This version has abstracted the data and graphics layers so that it is easy to reuse.
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
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.bar { | |
fill: steelblue; | |
} | |
.y.axis path { | |
display: none; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="http://underscorejs.org/underscore.js"></script> | |
<script> | |
var data = data; | |
d3.csv("data.csv", function(error, mydata) { | |
var ageNames = d3.keys(mydata[0]).filter(function(key) { return key !== "State"; }); | |
mydata.forEach(function(d) { | |
d.subgroups = ageNames.map(function(ageName) { return {subgroupLabel: ageName, value: +d[ageName]}; }); | |
d.groupLabel = d.State | |
}); | |
horizontalGroupedBarGraph(mydata, ageNames); | |
data = mydata; | |
}); | |
// data is a list of objects d | |
// d.groupLabel -> label for the group | |
// d.subgroups is a list of subgroup objects | |
// subgroup.subgroupLabel -> label | |
// subgroup.value -> value | |
function horizontalGroupedBarGraph(data) { | |
var subgroupLabels = _.union.apply(this, _.map(data, function(d) { | |
return _.map(d.subgroups, function(g) { return g.subgroupLabel; }); | |
})); | |
d3.keys(data[0]).filter(function(key) { return key !== "State"; }); | |
var margin = {top: 20, right: 20, bottom: 30, left: 40}, | |
width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var x = d3.scale.linear() | |
.range([0, width]); | |
var y0 = d3.scale.ordinal() | |
.rangeRoundBands([height, 0], .1); | |
var y1 = d3.scale.ordinal(); | |
var color = d3.scale.ordinal() | |
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom") | |
.tickFormat(d3.format(".2s")); | |
var yAxis = d3.svg.axis() | |
.scale(y0) | |
.orient("left"); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
y0.domain(data.map(function(d) { return d.groupLabel; })); | |
y1.domain(subgroupLabels).rangeRoundBands([0, y0.rangeBand()]); | |
x.domain([0, d3.max(data, function(d) { return d3.max(d.subgroups, function(d) { return d.value; }); })]); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis) | |
.append("text") | |
.attr("x", width) | |
.attr("dy", "-.71em") | |
.style("text-anchor", "end") | |
.text("Population"); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
var group = svg.selectAll(".group") | |
.data(data) | |
.enter().append("g") | |
.attr("class", "g") | |
.attr("transform", function(d) { return "translate(0," + y0(d.groupLabel) + ")"; }); | |
group.selectAll("rect") | |
.data(function(d) { return d.subgroups; }) | |
.enter().append("rect") | |
.attr("height", y1.rangeBand()) | |
.attr("x", 0) | |
.attr("y", function(d) { return y1(d.subgroupLabel); }) | |
.attr("width", function(d) { return x(d.value); }) | |
.style("fill", function(d) { return color(d.subgroupLabel); }); | |
var legend = svg.selectAll(".legend") | |
.data(subgroupLabels) | |
.enter().append("g") | |
.attr("class", "legend") | |
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; }); | |
legend.append("rect") | |
.attr("x", width - 18) | |
.attr("width", 18) | |
.attr("height", 18) | |
.style("fill", color); | |
legend.append("text") | |
.attr("x", width - 24) | |
.attr("y", 9) | |
.attr("dy", ".35em") | |
.style("text-anchor", "end") | |
.text(function(d) { return d; }); | |
} | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
On line 105 shouldn't the class be "group" to match the selectAll(".group"). It doesn't really matter here because you only have the enter() handler but cause trouble if you later wanted to handle update or exit.