A plot of US government spending over time with an animate pie chart showing the annual percentage breakdown by spending category.
Last active
December 16, 2015 07:09
-
-
Save whitews/5396879 to your computer and use it in GitHub Desktop.
US Government Spending
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
Year | NationalDefense | EduTrainEmploySocial | Health | Medicare | IncomeSecurity | SocialSecurity | Veterans | Interest | Other | |
---|---|---|---|---|---|---|---|---|---|---|
1940 | 1660 | 1972 | 55 | 0 | 1514 | 28 | 570 | 899 | 2770 | |
1941 | 6435 | 1592 | 60 | 0 | 1855 | 91 | 560 | 943 | 2117 | |
1942 | 25658 | 1062 | 71 | 0 | 1828 | 137 | 501 | 1052 | 4828 | |
1943 | 66699 | 375 | 92 | 0 | 1739 | 177 | 276 | 1529 | 7668 | |
1944 | 79143 | 160 | 174 | 0 | 1503 | 217 | -126 | 2219 | 8014 | |
1945 | 82965 | 134 | 211 | 0 | 1137 | 267 | 110 | 3112 | 4776 | |
1946 | 42681 | 85 | 201 | 0 | 2384 | 358 | 2465 | 4111 | 2947 | |
1947 | 12808 | 102 | 177 | 0 | 2820 | 466 | 6344 | 4204 | 7575 | |
1948 | 9105 | 191 | 162 | 0 | 2499 | 558 | 6457 | 4341 | 6451 | |
1949 | 13150 | 178 | 197 | 0 | 3174 | 657 | 6599 | 4523 | 10357 | |
1950 | 13724 | 241 | 268 | 0 | 4097 | 781 | 8834 | 4812 | 9805 | |
1951 | 23566 | 235 | 323 | 0 | 3352 | 1565 | 5526 | 4665 | 6282 | |
1952 | 46089 | 339 | 347 | 0 | 3655 | 2063 | 5341 | 4701 | 5151 | |
1953 | 52802 | 441 | 336 | 0 | 3823 | 2717 | 4519 | 5156 | 6307 | |
1954 | 49266 | 370 | 307 | 0 | 4434 | 3352 | 4613 | 4811 | 3702 | |
1955 | 42729 | 445 | 291 | 0 | 5071 | 4427 | 4675 | 4850 | 5956 | |
1956 | 42523 | 591 | 359 | 0 | 4734 | 5478 | 4891 | 5079 | 6985 | |
1957 | 45430 | 590 | 479 | 0 | 5427 | 6661 | 5005 | 5354 | 7632 | |
1958 | 46815 | 643 | 541 | 0 | 7535 | 8219 | 5350 | 5604 | 7698 | |
1959 | 49015 | 789 | 685 | 0 | 8239 | 9737 | 5443 | 5762 | 12428 | |
1960 | 48130 | 968 | 795 | 0 | 7378 | 11602 | 5441 | 6947 | 10930 | |
1961 | 49601 | 1063 | 913 | 0 | 9683 | 12474 | 5705 | 6716 | 11568 | |
1962 | 52345 | 1241 | 1198 | 0 | 9207 | 14365 | 5619 | 6889 | 15957 | |
1963 | 53400 | 1458 | 1451 | 0 | 9311 | 15788 | 5514 | 7740 | 16654 | |
1964 | 54757 | 1555 | 1788 | 0 | 9657 | 16620 | 5675 | 8199 | 20277 | |
1965 | 50620 | 2140 | 1791 | 0 | 9469 | 17460 | 5716 | 8591 | 22441 | |
1966 | 58111 | 4363 | 2543 | 64 | 9678 | 20694 | 5916 | 9386 | 23777 | |
1967 | 71417 | 6453 | 3351 | 2748 | 10261 | 21725 | 6735 | 10268 | 24506 | |
1968 | 81926 | 7634 | 4390 | 4649 | 11816 | 23854 | 7032 | 11090 | 25743 | |
1969 | 82497 | 7548 | 5162 | 5695 | 13076 | 27298 | 7631 | 12699 | 22034 | |
1970 | 81692 | 8634 | 5907 | 6213 | 15655 | 30270 | 8669 | 14380 | 24229 | |
1971 | 78872 | 9849 | 6843 | 6622 | 22946 | 35872 | 9768 | 14841 | 24559 | |
1972 | 79174 | 12529 | 8674 | 7479 | 27650 | 40157 | 10720 | 15478 | 28820 | |
1973 | 76681 | 12745 | 9356 | 8052 | 28276 | 49090 | 12003 | 17349 | 32155 | |
1974 | 79347 | 12457 | 10733 | 9639 | 33713 | 55867 | 13374 | 21449 | 32780 | |
1975 | 86509 | 16022 | 12930 | 12875 | 50176 | 64658 | 16584 | 23244 | 49334 | |
1976 | 89619 | 18910 | 15734 | 15834 | 60799 | 73899 | 18419 | 26727 | 51851 | |
1977 | 97241 | 21104 | 17302 | 19345 | 61060 | 85061 | 18022 | 29901 | 60182 | |
1978 | 104495 | 26710 | 18524 | 22768 | 61505 | 93861 | 18961 | 35458 | 76464 | |
1979 | 116342 | 30223 | 20494 | 26495 | 66376 | 104073 | 19914 | 42633 | 77478 | |
1980 | 133995 | 31843 | 23169 | 32090 | 86557 | 118547 | 21169 | 52533 | 91038 | |
1981 | 157513 | 33152 | 26866 | 39149 | 100299 | 139584 | 22973 | 68766 | 89939 | |
1982 | 185309 | 26612 | 27445 | 46567 | 108155 | 155964 | 23938 | 85032 | 86721 | |
1983 | 209903 | 26197 | 28641 | 52588 | 123031 | 170724 | 24824 | 89808 | 82648 | |
1984 | 227411 | 26920 | 30417 | 57540 | 113352 | 178223 | 25575 | 111102 | 81265 | |
1985 | 252743 | 28592 | 33541 | 65822 | 128979 | 188623 | 26251 | 129478 | 92315 | |
1986 | 273373 | 29776 | 35933 | 70164 | 120633 | 198757 | 26314 | 136017 | 99415 | |
1987 | 281996 | 28921 | 39964 | 75120 | 124088 | 207352 | 26729 | 138611 | 81236 | |
1988 | 290360 | 30931 | 44483 | 78878 | 130377 | 219341 | 29367 | 151803 | 88876 | |
1989 | 303555 | 35328 | 48380 | 84964 | 137426 | 232542 | 30003 | 168981 | 102565 | |
1990 | 299321 | 37171 | 57699 | 98102 | 148668 | 248623 | 29034 | 184347 | 150028 | |
1991 | 273285 | 41235 | 71168 | 104489 | 172462 | 269015 | 31275 | 194448 | 166849 | |
1992 | 298346 | 42741 | 89486 | 119024 | 199562 | 287584 | 34037 | 199344 | 111405 | |
1993 | 291084 | 47380 | 99401 | 130552 | 209969 | 304585 | 35642 | 198713 | 92060 | |
1994 | 281640 | 43286 | 107107 | 144747 | 217166 | 319565 | 37559 | 202932 | 107751 | |
1995 | 272063 | 51027 | 115399 | 159855 | 223799 | 335846 | 37862 | 232134 | 87757 | |
1996 | 265748 | 48321 | 119365 | 174225 | 229736 | 349671 | 36956 | 241053 | 95409 | |
1997 | 270502 | 48975 | 123832 | 190016 | 235032 | 365251 | 39283 | 243984 | 84241 | |
1998 | 268194 | 50512 | 131425 | 192822 | 237750 | 379215 | 41741 | 241118 | 109681 | |
1999 | 274769 | 50605 | 141048 | 190447 | 242478 | 390037 | 43155 | 229755 | 139548 | |
2000 | 294363 | 53764 | 154504 | 197113 | 253724 | 409423 | 46989 | 222949 | 156121 | |
2001 | 304732 | 57094 | 172233 | 217384 | 269774 | 432958 | 44974 | 206167 | 157530 | |
2002 | 348456 | 70566 | 196497 | 230855 | 312720 | 455980 | 50929 | 170949 | 173942 | |
2003 | 404744 | 82587 | 219541 | 249433 | 334632 | 474680 | 56984 | 153073 | 184225 | |
2004 | 455833 | 87974 | 240122 | 269360 | 333059 | 495548 | 59746 | 160245 | 190954 | |
2005 | 495308 | 97555 | 250548 | 298638 | 345847 | 523305 | 70120 | 183986 | 206650 | |
2006 | 521827 | 118482 | 252739 | 329868 | 352477 | 548549 | 69811 | 226603 | 234694 | |
2007 | 551271 | 91656 | 266382 | 375407 | 365975 | 586153 | 72818 | 237109 | 181915 | |
2008 | 616073 | 91287 | 280599 | 390758 | 431313 | 617027 | 84653 | 252757 | 218077 | |
2009 | 661049 | 79749 | 334335 | 430093 | 533224 | 682963 | 95429 | 186902 | 513933 | |
2010 | 693586 | 127710 | 369054 | 451636 | 622210 | 706737 | 108384 | 196194 | 180702 | |
2011 | 705625 | 101233 | 372500 | 485653 | 597352 | 730811 | 127189 | 229968 | 252730 |
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> | |
<html> | |
<head> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> | |
<title>US Government Spending</title> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script type="text/javascript"> | |
window.onload = function() { | |
var width = 960; | |
var height = 500; | |
var marginHorz = 75; | |
var marginVert = 25; | |
var opacity = 1.0; | |
var radius = 4.5; | |
var stroke = 1.0; | |
var strokeColor = "#333"; | |
var outerRadius = 140; | |
var innerRadius = 60; | |
var textOffset = 14; | |
var tweenDuration = 1000; | |
var dataDuration = 1500; | |
var updateInterval = window.setInterval(update, dataDuration); | |
var startYear = 1940; | |
var endYear = 2011; | |
var currentYear = startYear; | |
var startAmount = 0; | |
var endAmount = 750000; | |
// Stuff to be populated later | |
var paths; | |
var lines; | |
var valueLabels; | |
var pieChart = []; | |
var oldData = []; // for saving the previous angles for tweening | |
var spendingData; | |
var category = []; | |
var categoryLabels; | |
var categoryColor = []; | |
var yearData; | |
var yearTotalAmount; | |
///////////////////// | |
// PLACEMENT STUFF // | |
///////////////////// | |
var svg = d3.select("#graph").append("svg:svg") | |
.attr("width", width) | |
.attr("height", height); | |
// Pie Chart | |
var pie = svg.append("svg:g") | |
.attr("class", "pie") | |
.attr("transform", "translate(320, 240)"); | |
// Group together all the pie chart arcs & paths | |
var arc_group = pie.append("svg:g") | |
.attr("class", "arc"); | |
// Group our pie chart labels | |
var label_group = pie.append("svg:g") | |
.attr("class", "label_group"); | |
// Group our pie chart center label stuff | |
var center_group = pie.append("svg:g") | |
.attr("class", "center_group"); | |
var totalLabel = center_group.append("svg:text") | |
.attr("class", "label") | |
.attr("dy", -21) | |
.attr("text-anchor", "middle") // text-align: right | |
.text("TOTAL"); | |
var totalAmountLabel = center_group.append("svg:text") | |
.attr("class", "total") | |
.attr("dy", 12) | |
.attr("text-anchor", "middle") // text-align: right | |
.text("Loading..."); | |
var totalUnits = center_group.append("svg:text") | |
.attr("class", "units") | |
.attr("dy", 32) | |
.attr("text-anchor", "middle") // text-align: right | |
.text("billion"); | |
// Current Year Label | |
var currentYearLabel = center_group.append("svg:text") | |
.attr("class", "year") | |
.attr("dx", 300) | |
.attr("dy", -100) | |
.attr("text-anchor", "right") // text-align: right | |
// Plot axes | |
var x = d3.scale.linear() | |
.domain([startYear, endYear]) | |
.range([marginHorz, width-marginVert]); | |
var y = d3.scale.linear() | |
.domain([startAmount, endAmount]) | |
.range([height-marginVert, marginVert]); | |
// X-axis | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom"); | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(0," + (height - marginVert) + ")") | |
.call(xAxis); | |
// Y-axis | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left"); | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(" + marginHorz + ",0)") | |
.call(yAxis); | |
/////////////// | |
// LOAD DATA // | |
/////////////// | |
d3.csv("govt_spending.csv", function(csv) { | |
spendingData = csv; | |
for (var key in spendingData[0]) { | |
if (spendingData[0].hasOwnProperty(key)) { | |
category.push(key); | |
} | |
} | |
categoryColor = d3.scale.category10().domain(category); | |
for (var cat in category) { | |
if (category[cat] == "Year" || category[cat] === undefined) { | |
continue; | |
} | |
// Plot the data on the graph | |
svg.selectAll(category[cat]).data(spendingData).enter() | |
.append("circle") | |
.attr("cx", function(d) { return x(+d.Year); }) | |
.attr("cy", function(d) { return y(+d[category[cat]]); }) | |
.attr("r", radius) | |
.style("fill", categoryColor(category[cat])) | |
.style("opacity", opacity) | |
.style("stroke", strokeColor) | |
.style("stroke-width", stroke) | |
.append("title") | |
.text(function(d) { return category[cat] + ": " + d[category[cat]] }); | |
} | |
}); | |
/////////////// | |
// FUNCTIONS // | |
/////////////// | |
// D3 helper function to draw arcs, populates parameter "d" in path object | |
var arc = d3.svg.arc() | |
.startAngle(function(d){ return d.startAngle; }) | |
.endAngle(function(d){ return d.endAngle; }) | |
.innerRadius(innerRadius) | |
.outerRadius(outerRadius); | |
// Pull out data for one year as an array...spendingData is an array of objects | |
function getDataForYear(year) { | |
var yearData = []; | |
var object; | |
for (var i = 0; i < spendingData.length; i++) { | |
if (spendingData[i].Year === year.toString()) { | |
for (var c in category.sort()) { | |
if (spendingData[i].hasOwnProperty(category[c]) && category[c] !== "Year") { | |
object = new Object(); | |
object.category = category[c]; | |
object.amount = spendingData[i][category[c]]; | |
yearData.push(object); | |
} | |
} | |
} | |
} | |
return yearData; | |
} | |
// Update the pie chart | |
function update() { | |
if (currentYear > endYear) { | |
currentYear = startYear; | |
} | |
yearData = getDataForYear(currentYear); | |
yearTotalAmount = 0; | |
// Save the old paths so we can get the old angles for the tween animations | |
if (paths !== undefined) { | |
oldData = paths.data(); | |
} | |
// Associate our data with the arc and label groups | |
arc_group.data([yearData]); | |
label_group.data([yearData]); | |
// Create pie skeleton, must provide function for getting values | |
pieChart = d3.layout.pie() | |
.value(function(d) { return d.amount }) | |
.sort(null); | |
// Tally up the total amount & show it | |
yearData.forEach(function (y) { | |
yearTotalAmount += parseInt(y.amount, 10); | |
}); | |
totalAmountLabel.text(function() { | |
var billions = yearTotalAmount/1000; | |
return "$" + billions.toFixed(1); | |
}); | |
// Show the current year used for the pie graph | |
currentYearLabel.text(currentYear); | |
// Draw arc paths | |
paths = arc_group.selectAll("path").data(pieChart); // introduce our pie to the data | |
paths.enter().append("svg:path") | |
.attr("stroke", "white") | |
.attr("stroke-width", 0.5) | |
.attr("fill", function(d, i) { | |
return categoryColor(category[i]); | |
}) | |
.transition() | |
.duration(tweenDuration) | |
.attrTween("d", pieTween); | |
paths.transition() | |
.duration(tweenDuration) | |
.attrTween("d", pieTween); | |
paths.exit() | |
.transition() | |
.duration(tweenDuration) | |
.attrTween("d", removePieTween) | |
.remove(); | |
// Draw tick marks for the pie graph labels | |
lines = label_group.selectAll("line").data(pieChart); // introduce our pie to the data | |
lines.enter().append("svg:line") | |
.attr("x1", 0) | |
.attr("x2", 0) | |
.attr("y1", -outerRadius-1) | |
.attr("y2", -outerRadius-8) | |
.attr("stroke", "gray") | |
.attr("transform", function(d) { | |
return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")"; | |
}); | |
lines.transition() | |
.duration(tweenDuration) | |
.attr("transform", function(d) { | |
return "rotate(" + (d.startAngle+d.endAngle)/2 * (180/Math.PI) + ")"; | |
}); | |
lines.exit().remove(); | |
// Draw labels for percentage values | |
valueLabels = label_group.selectAll("text.value").data(pieChart) // introduce our pie to the data | |
.attr("dy", function(d) { | |
if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) { | |
return 5; | |
} | |
else { | |
return -7; | |
} | |
}) | |
.attr("text-anchor", function(d) { | |
if ( (d.startAngle+d.endAngle)/2 < Math.PI ) { | |
return "beginning"; | |
} else { | |
return "end"; | |
} | |
}) | |
.text(function(d) { | |
var percentage = (d.value/yearTotalAmount)*100; | |
return percentage.toFixed(1) + "%"; | |
}); | |
valueLabels.enter().append("svg:text") | |
.attr("class", "value") | |
.attr("transform", function(d) { | |
return "translate(" + Math.cos(((d.startAngle+d.endAngle - Math.PI)/2)) * (outerRadius+textOffset) + "," + Math.sin((d.startAngle+d.endAngle - Math.PI)/2) * (outerRadius+textOffset) + ")"; | |
}) | |
.attr("dy", function(d) { | |
if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) { | |
return 5; | |
} | |
else { | |
return -7; | |
} | |
}) | |
.attr("text-anchor", function(d) { | |
if ( (d.startAngle+d.endAngle)/2 < Math.PI ) { | |
return "beginning"; | |
} else { | |
return "end"; | |
} | |
}).text(function(d) { | |
var percentage = (d.value/yearTotalAmount)*100; | |
return percentage.toFixed(1) + "%"; | |
}); | |
valueLabels.transition().duration(tweenDuration).attrTween("transform", textTween); | |
valueLabels.exit().remove(); | |
// Draw category labels | |
categoryLabels = label_group.selectAll("text.units").data(pieChart) | |
.attr("dy", function(d) { | |
if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) { | |
return 21; | |
} else { | |
return 9; | |
} | |
}) | |
.attr("text-anchor", function(d) { | |
if ((d.startAngle+d.endAngle)/2 < Math.PI ) { | |
return "beginning"; | |
} else { | |
return "end"; | |
} | |
}).text(function(d) { | |
return d.data.category; | |
}); | |
categoryLabels.enter().append("svg:text") | |
.attr("class", "units") | |
.attr("transform", function(d) { | |
return "translate(" + Math.cos(((d.startAngle+d.endAngle - Math.PI)/2)) * (outerRadius+textOffset) + "," + Math.sin((d.startAngle+d.endAngle - Math.PI)/2) * (outerRadius+textOffset) + ")"; | |
}) | |
.attr("dy", function(d){ | |
if ((d.startAngle+d.endAngle)/2 > Math.PI/2 && (d.startAngle+d.endAngle)/2 < Math.PI*1.5 ) { | |
return 21; | |
} else { | |
return 9; | |
} | |
}) | |
.attr("text-anchor", function(d) { | |
if ((d.startAngle+d.endAngle)/2 < Math.PI ) { | |
return "beginning"; | |
} else { | |
return "end"; | |
} | |
}).text(function(d) { | |
return d.data.category; | |
}); | |
categoryLabels.transition().duration(tweenDuration).attrTween("transform", textTween); | |
categoryLabels.exit().remove(); | |
currentYear++; | |
} | |
// Animation for the pie arcs | |
function pieTween(d, i) { | |
var s0; | |
var e0; | |
if (oldData[i]) { | |
s0 = oldData[i].startAngle; | |
e0 = oldData[i].endAngle; | |
} else if (!(oldData[i]) && oldData[i-1]) { | |
s0 = oldData[i-1].endAngle; | |
e0 = oldData[i-1].endAngle; | |
} else if(!(oldData[i-1]) && oldData.length > 0) { | |
s0 = oldData[oldData.length-1].endAngle; | |
e0 = oldData[oldData.length-1].endAngle; | |
} else { | |
s0 = 0; | |
e0 = 0; | |
} | |
var i = d3.interpolate({startAngle: s0, endAngle: e0}, {startAngle: d.startAngle, endAngle: d.endAngle}); | |
return function(t) { | |
var b = i(t); | |
return arc(b); | |
}; | |
} | |
function removePieTween(d, i) { | |
s0 = 2 * Math.PI; | |
e0 = 2 * Math.PI; | |
var i = d3.interpolate({startAngle: d.startAngle, endAngle: d.endAngle}, {startAngle: s0, endAngle: e0}); | |
return function(t) { | |
var b = i(t); | |
return arc(b); | |
}; | |
} | |
// Animation for text | |
function textTween(d, i) { | |
var a; | |
if (oldData[i]) { | |
a = (oldData[i].startAngle + oldData[i].endAngle - Math.PI)/2; | |
} | |
else if (!(oldData[i]) && oldData[i-1]) { | |
a = (oldData[i-1].startAngle + oldData[i-1].endAngle - Math.PI)/2; | |
} | |
else if (!(oldData[i-1]) && oldData.length > 0) { | |
a = (oldData[oldData.length-1].startAngle + oldData[oldData.length-1].endAngle - Math.PI)/2; | |
} | |
else { | |
a = 0; | |
} | |
var b = (d.startAngle + d.endAngle - Math.PI)/2; | |
var fn = d3.interpolateNumber(a, b); | |
return function(t) { | |
var val = fn(t); | |
return "translate(" + Math.cos(val) * (outerRadius+textOffset) + "," + Math.sin(val) * (outerRadius+textOffset) + ")"; | |
}; | |
} | |
} | |
</script> | |
<style type='text/css'> | |
body { | |
margin: 0px; | |
} | |
.h,.v { | |
stroke:black; | |
stroke-dasharray: 4 4; | |
stroke-width: 1; | |
stroke-opacity: 0.5; | |
} | |
.axis path, | |
.axis line | |
{ | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
#graph { | |
background-color: #ffffff; | |
font: 10px sans-serif; | |
text-shadow: none; | |
} | |
#graph .total{ | |
font-size: 32px; | |
font-weight: bold; | |
} | |
#graph .units{ | |
fill: gray; | |
font-size: 14px; | |
} | |
#graph .label{ | |
fill: #CCC; | |
font-size: 14px; | |
font-weight: bold; | |
} | |
#graph .year{ | |
fill: #777; | |
font-size: 64px; | |
font-weight: bold; | |
} | |
#graph .value{ | |
font-size: 14px; | |
font-weight: bold; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="graph"></div> | |
</body> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment