Skip to content

Instantly share code, notes, and snippets.

@asifm
Last active December 7, 2015 21:01
Show Gist options
  • Save asifm/68587be7fc7df03c082a to your computer and use it in GitHub Desktop.
Save asifm/68587be7fc7df03c082a to your computer and use it in GitHub Desktop.
Interactive Stacked Chart
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>US Higher Education: Research Expenditure</title>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<style type="text/css">
body {
margin: 50px;
background-color: white;
font-family: Helvetica, Arial, sans-serif;
}
h1 {
font-size: 24px;
margin: 0;
}
p {
font-size: 14px;
margin: 10px 0 0 0;
}
svg {
background-color: white;
}
.area-all:hover {
fill: maroon;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<h1>Research Expenditure in US Higher Education by Source of Fund</h1>
<p>The chart below shows total research expenditure by US universities since 2000, broken down by source of fund.</p>
<p>Source: <a href="http://www.nsf.gov/statistics/herd/">Higher Education Research and Development (HERD) Survey</a></p>
<br>
<p>Double-click to see change in a specific source of fund.</p>
<p>Million USD</p>
<div id="source">
<h4></h4> </div>
<script type="text/javascript">
//Set up stack method
var stack = d3.layout.stack()
.values(function(d) {
return d.dollars;
})
.order("reverse");
//Width, height, padding
var w = 800;
var h = 400;
var padding = [20, 10, 40, 100]; //Top, right, bottom, left
//Set up date format function (years)
var dateFormat = d3.time.format("%Y");
//Set up scales
var xScale = d3.time.scale()
.range([padding[3], w - padding[1] - padding[3]]);
var yScale = d3.scale.linear()
.range([padding[0], h - padding[2]]);
//Configure axis generators
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(15)
.tickFormat(function(d) {
return dateFormat(d);
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Configure area generator
var area = d3.svg.area()
.x(function(d) {
return xScale(dateFormat.parse(d.x));
})
.y0(function(d) {
return yScale(d.y0); //Updated
})
.y1(function(d) {
return yScale(d.y0 + d.y); //Updated
});
//Easy colors accessible via a 10-step ordinal scale
var color = d3.scale.category20b();
//Create the empty SVG image
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load data
d3.csv("research-fund-source.csv", function(data) {
//New array with all the years, for referencing later
var years = ["2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013"];
//Create a new, empty array to hold our restructured dataset
var dataset = [];
//Loop once for each row in data
for (var i = 0; i < data.length; i++) {
dataset[i] = {
source: data[i].Source,
dollars: []
};
//Loop through all the years
for (var j = 0; j < years.length; j++) {
//Default value, used in case no value is present
var amount = null;
// If value is not empty
if (data[i][years[j]]) {
amount = +data[i][years[j]];
}
dataset[i].dollars.push({
x: years[j],
y: amount
});
}
}
stack(dataset);
xScale.domain([
d3.min(years, function(d) {
return dateFormat.parse(d);
}),
d3.max(years, function(d) {
return dateFormat.parse(d);
})
]);
var totals = [];
for (i = 0; i < years.length; i++) {
totals[i] = 0;
for (j = 0; j < dataset.length; j++) {
totals[i] += dataset[j].dollars[i].y;
}
}
yScale.domain([d3.max(totals), 0]);
// flag to check if all stacked area is currently shown
var allShown = 1;
d3.select("#source h4")
.text("All sources")
var paths = svg.selectAll(".area-all")
.data(dataset)
.enter()
.append("path")
.attr("class", "area-all")
.attr("d", function(d) {
return area(d.dollars);
})
.attr("stroke", "none")
.attr("fill", function(d, i) {
return color(i);
})
.on("dblclick", function(d) {
if (allShown === 1) {
allShown = 0;
showArea(d);
}
});;
function showArea(d) {
svg.selectAll(".area-all")
.attr("opacity", 0);
svg.selectAll(".area")
.classed("area", false);
d3.select("#source h4")
.text(d.source)
svg.selectAll(".area")
.data([d])
.enter()
.append("path")
.attr("class", "area")
.attr("d", function(d) {
for (var i = d.dollars.length - 1; i >= 0; i--) {
d.dollars[i].y0 = 0;
};
return area(d.dollars);
})
.attr("stroke", "none")
.attr("opacity", 1)
.attr("fill", "maroon")
.on("dblclick", showAreaAll);
}
function showAreaAll() {
allShown = 1;
d3.select("#source h4")
.text("All sources")
svg.selectAll(".area")
.transition()
.attr("opacity", 0)
svg.selectAll(".area")
.remove()
svg.selectAll(".area-all")
.transition()
.attr("opacity", 1)
}
paths.append("title")
.text(function(d) {
return d.source;
});
//Create axes
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (h - padding[2]) + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + padding[3] + ",0)")
.call(yAxis);
});
</script>
</body>
</html>
Source 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013
All other sources 2255 2422 2698 2856 2851 3092 3198 3521 3916 4294 4454 4548 4609 5015
Business 2156 2218 2191 2161 2129 2291 2401 2675 2869 3197 3117 3095 3192 3426
Institution funds 5925 6614 7133 7663 7752 8265 9062 9718 10378 11148 10674 11132 12035 13261
State and local government 2200 2320 2504 2645 2879 2940 2966 3151 3438 3647 3605 3574 3432 3398
Federal government 17548 19227 21856 24753 27627 29187 30132 30430 31272 32576 36510 39652 38954 38294
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment