Stacked Bar chart of job distribution in the 9 county SF Bay Area from 2002 – 2015.
This variation of a stacked bar chart shows percentages rather than absolute numbers.
forked from mbostock's block: Normalized Stacked Bar Chart
| license: gpl-3.0 |
Stacked Bar chart of job distribution in the 9 county SF Bay Area from 2002 – 2015.
This variation of a stacked bar chart shows percentages rather than absolute numbers.
forked from mbostock's block: Normalized Stacked Bar Chart
| year | makers | services | professions | support | all | |
|---|---|---|---|---|---|---|
| 2002 | 845976 | 836274 | 719462 | 796246 | 3197958 | |
| 2003 | 782889 | 823079 | 679760 | 794857 | 3080585 | |
| 2004 | 774831 | 817061 | 673196 | 786663 | 3051751 | |
| 2005 | 790634 | 834913 | 680094 | 781862 | 3087503 | |
| 2006 | 790769 | 843916 | 698395 | 801632 | 3134712 | |
| 2007 | 808558 | 854848 | 704257 | 840688 | 3208351 | |
| 2008 | 786034 | 854061 | 706370 | 894112 | 3240577 | |
| 2009 | 728030 | 790862 | 688202 | 912137 | 3119231 | |
| 2010 | 705744 | 804637 | 684297 | 964995 | 3159673 | |
| 2011 | 712845 | 828965 | 718965 | 976399 | 3237174 | |
| 2012 | 716963 | 867654 | 749794 | 963670 | 3298081 | |
| 2013 | 733019 | 913297 | 804682 | 994328 | 3445326 | |
| 2014 | 766057 | 954828 | 831186 | 1013606 | 3565677 | |
| 2015 | 799916 | 985787 | 887679 | 1056618 | 3730000 |
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .bar { | |
| fill: steelblue; | |
| } | |
| .axis path { | |
| display: none; | |
| } | |
| </style> | |
| <svg width="960" height="500"></svg> | |
| <script src="//d3js.org/d3.v4.min.js"></script> | |
| <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
| <script> | |
| var svg = d3.select("svg"), | |
| margin = {top: 20, right: 60, 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 x = d3.scaleBand() | |
| .rangeRound([0, width]) | |
| .padding(0.1) | |
| .align(0.1); | |
| var y = d3.scaleLinear() | |
| .rangeRound([height, 0]); | |
| var z = d3.scaleOrdinal(d3.schemePastel1) | |
| var stack = d3.stack() | |
| .offset(d3.stackOffsetExpand); | |
| var format = d3.format(".2f") | |
| d3.csv("data.csv", type, function(error, data) { | |
| if (error) throw error; | |
| data.columns.pop(); // don't need "all" | |
| data.sort(function(a, b) { | |
| return b[data.columns[1]] / b.total - a[data.columns[1]] / a.total; | |
| }); | |
| console.log(data) | |
| x.domain(data.map(function(d) { return +d.year; }).sort()); | |
| z.domain(data.columns.slice(1)); | |
| var serie = g.selectAll(".serie") | |
| .data(stack.keys(data.columns.slice(1))(data)) | |
| .enter().append("g") | |
| .attr("class", "serie") | |
| .attr("fill", function(d) { return z(d.key); }); | |
| serie.selectAll("rect") | |
| .data(function(d) { return d; }) | |
| .enter().append("rect") | |
| .attr("x", function(d) { return x(d.data.year); }) | |
| .attr("y", function(d) { return y(d[1]); }) | |
| .attr("height", function(d) { return y(d[0]) - y(d[1]); }) | |
| .attr("width", x.bandwidth()) | |
| .each(function(d) { | |
| console.log(d, this) | |
| var el = d3.select(this) | |
| el.append("title").text(format(d[1] - d[0]) + "%") | |
| }) | |
| g.append("g") | |
| .attr("class", "axis axis--x") | |
| .attr("transform", "translate(0," + height + ")") | |
| .call(d3.axisBottom(x)); | |
| g.append("g") | |
| .attr("class", "axis axis--y") | |
| .call(d3.axisLeft(y).ticks(10, "%")); | |
| var legend = serie.append("g") | |
| .attr("class", "legend") | |
| .attr("transform", function(d) { | |
| var d = d.find(d2 => d2.data.year === 2015) | |
| return "translate(" + | |
| (x(d.data.year) + x.bandwidth()) + "," + | |
| ((y(d[0]) + y(d[1])) / 2) + ")"; | |
| }); | |
| legend.append("line") | |
| .attr("x1", -6) | |
| .attr("x2", 6) | |
| .attr("stroke", "#000"); | |
| legend.append("text") | |
| .attr("x", 9) | |
| .attr("dy", "0.35em") | |
| .attr("fill", "#000") | |
| .style("font", "10px sans-serif") | |
| .text(function(d) { return d.key; }); | |
| }); | |
| function type(d, i, columns) { | |
| for (i = 0, t = 0; i < columns.length; ++i) { | |
| d[columns[i]] = +d[columns[i]]; | |
| } | |
| d.total = +d.all; | |
| delete d.all; | |
| return d; | |
| } | |
| </script> |