This gist visualizes absolute log GDP values together with growth rates. The data is from The World Bank, and it is stored in a private gist 274e242ead103b56be3e.
Last active
August 29, 2015 14:16
-
-
Save cgroll/8312be4e639e2ca64779 to your computer and use it in GitHub Desktop.
Absolute GDP values and growth rates
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
// define margins | |
var margin = {top: 20, right: 80, bottom: 30, left: 150}; | |
// graphics size without axis | |
var width = 960 - margin.left - margin.right; | |
var height = 380 - margin.top - margin.bottom; | |
var svg1 = 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 + ")"); | |
var svg2 = 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 + ")"); | |
// axes scales | |
var x = d3.time.scale() | |
.range([0, width]); | |
var y = d3.scale.log() | |
.range([height, 0]); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom"); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5); | |
var yGrowth = d3.scale.linear() | |
.range([height, 0]); | |
var yAxisGrowth = d3.svg.axis() | |
.scale(yGrowth) | |
.orient("left") | |
.ticks(5); | |
// parse dates and remove missing values | |
var parseDate = d3.time.format("%Y-%m-%d").parse; | |
// log scale for y axis | |
var line = d3.svg.line() | |
.defined(function(d) { return !isNaN(d.lev); }) | |
// .interpolate("basis") | |
.x(function(d) { return x(d.idx); }) | |
.y(function(d) { return y(d.lev); }); | |
// linear scale for y axis | |
var growthLine = d3.svg.line() | |
.defined(function(d) { return !isNaN(d.diff); }) | |
.x(function(d) { return x(d.idx); }) | |
.y(function(d) { return yGrowth(d.diff); }); | |
// load data | |
queue() | |
.defer(d3.csv, "/cgroll/raw/274e242ead103b56be3e/isoCodes.csv") | |
.defer(d3.csv, "/cgroll/raw/274e242ead103b56be3e/ctryGdp.csv") | |
.defer(d3.csv, "/cgroll/raw/274e242ead103b56be3e/ctryQuantiles.csv") | |
.await(makeChart); | |
function makeChart(error, iso2Codes, ctryGdp, ctryQuantiles, ctryGdpGrowth){ | |
// create associated array for iso code to country name conversion | |
var ctryLookup = new Array(); | |
for (i = 0; i < iso2Codes.length; i++) { | |
ctryLookup[iso2Codes[i].iso2c] = iso2Codes[i].name; | |
} | |
// get country and quantile names | |
var countryNames = d3.keys(ctryGdp[0]).filter(function(key) { return key !== "idx"; }); | |
var quantNames = d3.keys(ctryQuantiles[0]).filter(function(key) { return key !== "idx"; }); | |
// parse dates | |
ctryGdp.forEach(function(d) { | |
d.idx = parseDate(d.idx); | |
}); | |
ctryQuantiles.forEach(function(d) { | |
d.idx = parseDate(d.idx); | |
}); | |
// get gdp level data as array | |
var gdpData = countryNames.map(function(name) { | |
countryData = ctryGdp.map(function(d, i) { | |
if (!i) {return {idx: d.idx, lev: +d[name], country: name, diff: NaN}} | |
else { | |
var diff = Math.log(+d[name]) - Math.log(ctryGdp[(i-1)][name]); | |
return {idx: d.idx, lev: +d[name], country: name, diff: diff} | |
}; | |
}) | |
return {country: name, | |
values: countryData | |
}; | |
}); | |
// get quantile data as array | |
var quants = quantNames.map(function(name) { | |
quants = ctryQuantiles.map(function(d) { | |
return {idx: d.idx, diff: +d[name]}; | |
}) | |
return {country: name, | |
values: quants | |
}; | |
}); | |
// get axis domains | |
x.domain(d3.extent(ctryGdp, function(d) { return d.idx; })); | |
y.domain([ | |
d3.min(gdpData, function(c) { return d3.min(c.values, function(v) { return v.lev; }); }), | |
d3.max(gdpData, function(c) { return d3.max(c.values, function(v) { return v.lev; }); }) | |
]); | |
// adjust limits to growth rates, not to quantiles | |
yGrowth.domain([-0.5, 0.5 | |
// d3.min(gdpData, function(c) { return d3.min(c.values, function(v) { return v.diff; }); }), | |
// d3.max(gdpData, function(c) { return d3.max(c.values, function(v) { return v.diff; }); }) | |
]); | |
// append axis for gpd level data | |
svg1.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
svg1.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.text("GDP p. cap., in thousand $"); | |
// append axis for gpd growth data | |
svg2.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
svg2.append("g") | |
.attr("class", "y axis") | |
.call(yAxisGrowth) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.text("GDP growth"); | |
// draw gdp level data | |
var gdp = svg1.selectAll(".gdp") | |
.data(gdpData) | |
.enter() | |
.append("g") | |
.attr("class", "gdp") | |
.append("path") | |
.attr("class", "line") | |
.attr("id", "inactive") | |
.attr("d", function(d) { d.gdpLine = this; return line(d.values); }) | |
.on("mouseover", onmouseover) | |
.on("mouseout", onmouseout) | |
.on("click", clickFunction); | |
function onmouseover(d, i) { | |
d3.select(this).attr("class", "line--hover"); | |
d3.select(d.growth).attr("d", function(c) { return growthLine(c.values); }); | |
d3.select(d.growth).attr("class", "line--hover"); | |
// transform iso2c code to name | |
var ctryName; | |
ctryName = ctryLookup[this.__data__.country] | |
d3.selectAll("h2").text(ctryName) | |
} | |
function onmouseout(d, i) { | |
d3.select(this).attr("class", "line"); | |
if (this.id == "active") {d3.select(d.growth).attr("class", "line");} | |
else { | |
d3.select(d.growth).attr("d", null); | |
} | |
d3.selectAll("h2").text("World") | |
} | |
function clickFunction(d, i) { | |
if (this.id == "inactive") { | |
d3.select(this).attr("id", "active"); | |
d3.select(d.growth).attr("d", function(c) { return growthLine(c.values); }); | |
d3.select(d.growth).attr("id", "active"); | |
} | |
else { | |
d3.select(this).attr("id", "inactive"); | |
d3.select(d.growth).attr("d", null); | |
}; | |
} | |
// append empty paths for growth rates | |
var qs = svg2.selectAll(".growth") | |
.data(gdpData) | |
.enter() | |
.append("g") | |
.attr("class", "growth") | |
.append("path") | |
.attr("class", function(d) { d.growth = this; return "line--hover"; }) | |
// .attr("d", function(d) { d.line = this; return growthLine(d.values); }); | |
// draw quantiles | |
var qs = svg2.selectAll(".quant") | |
.data(quants) | |
.enter() | |
.append("g") | |
.attr("class", "quant") | |
.append("path") | |
.attr("d", function(d) { d.line = this; return growthLine(d.values); }); | |
}; |
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> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font: 16px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.x.axis path { | |
<!-- display: none; --> | |
} | |
.line, | |
.line#inactive { | |
fill: none; | |
stroke: gray; | |
stroke-width: 1.5px; | |
stroke-opacity: 0.2; | |
} | |
.quant { | |
fill: none; | |
stroke: lightblue; | |
stroke-width: 1.0px; | |
stroke-opacity: 1; | |
} | |
.grid .tick { | |
stroke: lightgrey; | |
stroke-opacity: 0.7; | |
shape-rendering: crispEdges; | |
} | |
.grid path { | |
stroke-width: 0; | |
} | |
.line--hover, | |
.line--hover#active, | |
.line--hover#inactive { | |
fill: none; | |
stroke: darkred; | |
stroke-width: 3.5px; | |
stroke-opacity: 1; | |
} | |
.line#active { | |
fill: none; | |
stroke: black; | |
stroke-width: 2.5px; | |
stroke-opacity: 0.7; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="http://d3js.org/queue.v1.min.js"></script> | |
<h2>World</h2> | |
<script src="assembly_code.js"> | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment