Skip to content

Instantly share code, notes, and snippets.

@mbostock

mbostock/.block

Forked from mbostock/.block
Last active Sep 7, 2020
Embed
What would you like to do?
Grouped Bar Chart
license: gpl-3.0
redirect: https://observablehq.com/@d3/grouped-bar-chart

This grouped bar chart is constructed from a CSV file storing the populations of different states by age group. The chart employs conventional margins and a number of D3 features:

State Under 5 Years 5 to 13 Years 14 to 17 Years 18 to 24 Years 25 to 44 Years 45 to 64 Years 65 Years and Over
CA 2704659 4499890 2159981 3853788 10604510 8819342 4114496
TX 2027307 3277946 1420518 2454721 7017731 5656528 2472223
NY 1208495 2141490 1058031 1999120 5355235 5120254 2607672
FL 1140516 1938695 925060 1607297 4782119 4746856 3187797
IL 894368 1558919 725973 1311479 3596343 3239173 1575308
PA 737462 1345341 679201 1203944 3157759 3414001 1910571
<!DOCTYPE html>
<style>
.axis .domain {
display: none;
}
</style>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.1);
var x1 = d3.scaleBand()
.padding(0.05);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
d3.csv("data.csv", function(d, i, columns) {
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
return d;
}, function(error, data) {
if (error) throw error;
var keys = data.columns.slice(1);
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();
g.append("g")
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; })
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return y(d.value); })
.attr("width", x1.bandwidth())
.attr("height", function(d) { return height - y(d.value); })
.attr("fill", function(d) { return z(d.key); });
g.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x0));
g.append("g")
.attr("class", "axis")
.call(d3.axisLeft(y).ticks(null, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks().pop()) + 0.5)
.attr("dy", "0.32em")
.attr("fill", "#000")
.attr("font-weight", "bold")
.attr("text-anchor", "start")
.text("Population");
var legend = g.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(keys.slice().reverse())
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width - 19)
.attr("width", 19)
.attr("height", 19)
.attr("fill", z);
legend.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) { return d; });
});
</script>
@mfazekas

This comment has been minimized.

Copy link

@mfazekas mfazekas commented Aug 14, 2015

At https://gist.github.com/mbostock/3887051#file-index-html-L90

 .attr("class", "g")

should be

 .attr("class", "state")

i assume

@railto

This comment has been minimized.

Copy link

@railto railto commented Feb 10, 2016

Thanks for this, really helpful in creating a grouped chart, one question tho, do you know of how to make a chart like this responsive to resize on smaller devices?

@ruben-romar

This comment has been minimized.

Copy link

@ruben-romar ruben-romar commented Jul 26, 2016

HI, thanks for the example, it really helped me. One question thou, is it possible to add the legend texts in the xaxis for every state? I am trying to do this in my code but I cannot make it work but for the first group....

@wannabecoding

This comment has been minimized.

Copy link

@wannabecoding wannabecoding commented Dec 16, 2016

Hi guys. Any idea why I can't get this to work locally? I am trying to use with the non-minified d3.js file.

@kannextic

This comment has been minimized.

Copy link

@kannextic kannextic commented Mar 30, 2017

@wannabecoding Probably because the browers block the loading of external csv files.

@SameerMandavia

This comment has been minimized.

Copy link

@SameerMandavia SameerMandavia commented Sep 7, 2020

.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })

How to convert this line into typescript? Because i don't get data in a proper manner
my Dummy data :-
label: 'January',
sticksList: [
{
sticksSublist: [
{ value: 25, color: 'green' },
{ value: 22, color: 'gray' },
{ value: 17, color: 'red' },
{ value: 10, color: 'black' },
],
},
],
and this value i want to show on graph.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.