Skip to content

Instantly share code, notes, and snippets.

@kcsluis
Last active May 2, 2019 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kcsluis/875d1b1a48b737567388 to your computer and use it in GitHub Desktop.
Save kcsluis/875d1b1a48b737567388 to your computer and use it in GitHub Desktop.
Jobs Growth Under Obama
<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
/*svg {*/
/* border: 1px solid #f0f;*/
/*}*/
body {
font-family: 'arial', sans-serif;
font-size: 9px;
}
h1 {
font-size: 36px;
}
.barPositive {
fill: #069;
}
.barNegative {
fill: lightGray;
}
.axis path {
display: none;
}
.axis line {
stroke-width: 1px;
stroke: #ccc;
stroke-dasharray: 2px 2px;
}
.xAxis {
font-weight: bold;
}
.label {
fill: #AAA;
}
.streakLine {
stroke: #069;
stroke-width: 3px;
}
.streakLabel {
text-anchor: middle;
fill: #069;
font-weight: bold;
font-size: 15px;
}
</style>
<body>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script>
// additional data sourced from
// http://data.bls.gov/timeseries/CES0000000001?output_view=net_1mth
// okay to keep these global
var marginCore = 20;
var margin = {top: 60, right: marginCore, bottom: 20, left: marginCore};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
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 + ")");
d3.tsv("jobs.tsv", function(error, data) {
if (error) throw error;
// data is an object, but now we need arrays
data.forEach( function (d) {
d.jobs_change = +d.jobs_change;
d.private_job_change = +d.private_job_change;
d.private_job_change = +d.private_job_change;
var s = d.month_year.split("-");
d.date = new Date(s[0], (+s[1]-1) );
});
// use map to strip out jobs_change
var jobs = data.map( function (d) { return d.jobs_change; });
var months = data.map( function (d) { return d.month_year; });
// reduce, anyone?
var totalJobsChange = jobs.reduce( function (a, b) {
return a+b;
});
var totalJobsIncrease = jobs.reduce ( function (a, b) {
return (b > 0) ? a+b : a;
});
data.sort( function (a,b) { return a.date - b.date; });
// console.log(data);
// console.log(jobs);
// console.log(months);
var jobsMin = d3.min(jobs);
var jobsMax = d3.max(jobs);
// console.log(jobsMin, jobsMax);
var xScale = d3.scale.ordinal()
.rangeRoundBands([0, width], 0.333)
.domain(months);
var yScale = d3.scale.linear()
.range([height, 0])
.domain([jobsMin, jobsMax]);
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(-width+35)
.tickPadding(6)
.orient("left");
// could use some pointers about abstracting out this function / variable access
// kFormat = function (number) {
// return (number > 0) ? "+" + d + "k" : d + "k";
// };
// var changeLabel;
// function kFormat(number) {
// return (number > 0) ? "+" + d + "k" : d + "k";
// };
// adding yAxis up so it draws below bars
svg.append("g")
.attr("class", "axis")
.call(yAxis)
.attr("transform", "translate(18,0)")
.selectAll("text")
.text( function (d) {
var changeLabel = d;
return d = (changeLabel > 0) ? "+" + d + "k" : d + "k";
});
// .text( function (d) {
// console.log(d);
// var changeLabel = d;
// return kFormat(changeLabel);
// });
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(0)
.tickPadding(6)
.orient("bottom");
var bars = svg.selectAll("bars")
.data(data)
.enter()
.append("rect")
.attr('class', function (d) {
if (d.jobs_change > 0) { return 'bar barPositive'}
else { return 'bar barNegative'};
})
.attr('x', function(d) { return xScale(d.month_year); })
.attr("width", xScale.rangeBand())
// this returns the higher of either d.jobs_change (so, positive numbers) or 0
.attr('y', function(d) { return yScale(Math.max(d.jobs_change, 0)); })
// this returns height as absolute value of change minus scaled value of 0
.attr("height", function(d) { return Math.abs(yScale(d.jobs_change) - yScale(0)); });
svg.append("line")
.attr('x1', 17)
.attr("x2", width-17)
.attr("y1", yScale(0))
.attr("y2", yScale(0))
.style("stroke", "#333")
.style("stroke-width", 1);
svg.append("g")
.attr("class", "xAxis")
.call(xAxis)
.attr("transform", "translate(0," + yScale(0) + ")")
.selectAll("g")
// yadda yadda yadda, use if then to add custom classes
.attr("class", function (d) { return d })
.selectAll("text")
.text(function (d) {
var dateSplit = d.split("-");
if ( dateSplit[1] === "01" ) {
return dateSplit[0];
};
});
function formatNumber (num) {
return num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
};
// labels
svg.append("text")
.attr("class", "label")
.attr("transform", "translate(-10,-25)")
.style("font-size", "13px")
.text(function() {
var tJS = "+" + formatNumber(totalJobsChange) + "k";
var tJI = "+" + formatNumber(totalJobsIncrease) + "k";
return "Overall Increase in Jobs: " + tJS + " | Total Jobs Added: " + tJI;
});
svg.append("text")
.attr("class", "label")
.attr("transform", "translate(-10,-40)")
.text("Monthly Change in U.S. Nonfarm Jobs for Extent of Obama Administration");
// streak label
// draw a line from october 2010 to last positive month
// then below and centered
// add a label that counts number of positive months
var mnth, stopStreakMonth;
var startStreakMonth = 21;
// there's probably a more elegant way to do this
for (mnth = startStreakMonth; mnth < data.length; mnth++) {
if (data[mnth].jobs_change < 0) {
stopStreakMonth = mnth;
mnth = data.length;
} else {
stopStreakMonth = data.length-1;
};
};
var firstStreakMonth = xScale(months[startStreakMonth]);
var lastStreakMonth = xScale(months[stopStreakMonth]);
var lengthOfStreak = stopStreakMonth - startStreakMonth;
var labelBelowZero = yScale(0)+25;
svg.append("g")
.attr("class", "streakLabel")
.attr("transform", "translate(" + xScale.rangeBand()/2 + ",0)")
.append("line")
.attr("class", "streakLine")
.attr('x1', firstStreakMonth)
.attr("x2", lastStreakMonth)
.attr("y1", labelBelowZero)
.attr("y2", labelBelowZero);
svg.select(".streakLabel")
.append("text")
.attr("x", (lastStreakMonth - firstStreakMonth)/2 + firstStreakMonth)
.attr("y", labelBelowZero+20)
.text(lengthOfStreak + " Months of Continued Jobs Growth");
});
</script>
month_year jobs_change private_job_change unemployment_rate
2009-01 -818 -839 7.8
2009-02 -724 -725 8.3
2009-03 -799 -787 8.7
2009-04 -692 -802 8.9
2009-05 -361 -312 9.4
2009-06 -482 -426 9.5
2009-07 -339 -296 9.5
2009-08 -231 -219 9.6
2009-09 -199 -184 9.8
2009-10 -202 -232 10
2009-11 -42 -42 9.9
2009-12 -171 -120 9.9
2010-01 -40 -40 9.7
2010-02 -35 -27 9.8
2010-03 189 141 9.8
2010-04 239 193 9.9
2010-05 516 84 9.6
2010-06 -167 92 9.4
2010-07 -58 92 9.5
2010-08 -51 128 9.6
2010-09 -27 115 9.5
2010-10 220 196 9.5
2010-11 121 134 9.8
2010-12 120 140 9.4
2011-01 110 119 9.1
2011-02 220 257 9
2011-03 246 261 8.9
2011-04 251 264 9
2011-05 54 108 9
2011-06 84 102 9.1
2011-07 96 175 9.1
2011-08 85 52 9.1
2011-09 202 216 9
2011-10 112 139 8.9
2011-11 157 178 8.7
2011-12 223 234 8.5
2012-01 275 277 8.3
2012-02 259 254 8.3
2012-03 143 147 8.2
2012-04 68 85 8.1
2012-05 87 116 8.2
2012-06 45 63 8.2
2012-07 181 163 8.3
2012-08 142 97 8.1
2012-09 114 104 7.8
2012-10 213 0 0
2012-11 164 0 0
2012-12 293 0 0
2013-01 205 0 0
2013-02 314 0 0
2013-03 115 0 0
2013-04 187 0 0
2013-05 219 0 0
2013-06 127 0 0
2013-07 164 0 0
2013-08 256 0 0
2013-09 150 0 0
2013-10 225 0 0
2013-11 317 0 0
2013-12 109 0 0
2014-01 166 0 0
2014-02 188 0 0
2014-03 225 0 0
2014-04 330 0 0
2014-05 236 0 0
2014-06 286 0 0
2014-07 249 0 0
2014-08 213 0 0
2014-09 250 0 0
2014-10 221 0 0
2014-11 423 0 0
2014-12 329 0 0
2015-01 201 0 0
2015-02 266 0 0
2015-03 119 0 0
2015-04 187 0 0
2015-05 254 0 0
2015-06 223 0 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment