Skip to content

Instantly share code, notes, and snippets.

@nkhine
Forked from mbostock/.block
Created July 10, 2012 10:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nkhine/3082578 to your computer and use it in GitHub Desktop.
Save nkhine/3082578 to your computer and use it in GitHub Desktop.
The Euro Debt Crisis

Bill Marsh created a nice visual guide to the Euro debt crisis in today’s New York Times using a custom graph layout with directed edges. An alternative approach to visualizing asymmetric relationships among a group of entities is a chord diagram. Chord diagrams don’t show indirect relationships as well, but they better convey the magnitudes of the debt for each country.

This visualization uses two chord diagrams. The diagram on the left emphasizes how much each country lends (creditors); you can see Japan and France are the biggest lenders, but France is also the most exposed by its risky debts to Italy and Greece. The diagram on the right emphasizes how much each country owes (debtors); the United States has by far the largest debt, nearly three times the size of the next-largest debtor, Britain!

Built with D3.js.

creditor debtor amount risk
Britain France 22.4 3
Britain Greece 0.55 0
Britain Italy 26 0
Britain Portugal 19.4 0
Britain United States 345 1
France Germany 53.8 1
France Greece 53.9 0
France Ireland 17.3 0
France Italy 366 0
France Japan 7.73 1
France Portugal 18.3 0
France Spain 118 2
France United States 322 1
Germany Britain 321 1
Germany Greece 19.3 0
Germany Ireland 48.9 0
Germany Portugal 32.5 0
Germany Spain 57.6 2
Germany United States 324 1
Ireland Britain 12 1
Ireland Greece 0.34 0
Ireland Spain 6.38 2
Italy Germany 111 1
Italy Greece 3.22 0
Italy Ireland 2.83 0
Italy Portugal 0.87 0
Japan Britain 28.2 1
Japan Germany 88.5 1
Japan Greece 1.37 0
Japan Ireland 18.9 0
Japan Italy 38.8 0
Japan Portugal 2.18 0
Japan Spain 25.9 2
Japan United States 796 1
Portugal Greece 10.1 0
Portugal Ireland 3.77 0
Portugal United States 0.52 1
Spain Britain 326 1
Spain Greece 0.78 0
Spain Italy 9.79 0
Spain Portugal 62 0
Spain United States 163 1
United States Greece 3.1 0
United States Ireland 11.1 0
United States Italy 3.16 0
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>The Euro Debt Crisis</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.4.6"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.layout.js?2.4.6"></script>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.csv.js?2.4.6"></script>
<style type="text/css">
.group text {
font: 11px sans-serif;
pointer-events: none;
}
.group path {
stroke: #000;
}
path.chord {
stroke-width: .75;
fill-opacity: .75;
}
</style>
</head>
<body>
<script type="text/javascript">
// Chart dimensions.
var w = 480,
h = 500,
r1 = Math.min(w, h) / 2 - 4,
r0 = r1 - 20,
format = d3.format(",.3r");
// Square matrices, asynchronously loaded; credits is the transpose of debits.
var debits = [],
credits = [];
// The chord layout, for computing the angles of chords and groups.
var layout = d3.layout.chord()
.sortGroups(d3.descending)
.sortSubgroups(d3.descending)
.sortChords(d3.descending)
.padding(.04);
// The color scale, for different categories of "worrisome" risk.
var fill = d3.scale.ordinal()
.domain([0, 1, 2])
.range(["#DB704D", "#D2D0C6", "#ECD08D", "#F8EDD3"]);
// The arc generator, for the groups.
var arc = d3.svg.arc()
.innerRadius(r0)
.outerRadius(r1);
// The chord generator (quadratic Bézier), for the chords.
var chord = d3.svg.chord()
.radius(r0);
// Add an SVG element for each diagram, and translate the origin to the center.
var svg = d3.select("body").selectAll("div")
.data([debits, credits])
.enter().append("div")
.style("display", "inline-block")
.style("width", w + "px")
.style("height", h + "px")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
// Load our data file…
d3.csv("debt.csv", function(data) {
var countries = {},
array = [],
n = 0;
// Compute a unique id for each country.
data.forEach(function(d) {
d.creditor = country(d.creditor);
d.debtor = country(d.debtor);
d.debtor.risk = d.risk;
d.valueOf = value; // convert object to number implicitly
});
// Initialize a square matrix of debits and credits.
for (var i = 0; i < n; i++) {
debits[i] = [];
credits[i] = [];
for (var j = 0; j < n; j++) {
debits[i][j] = 0;
credits[i][j] = 0;
}
}
// Populate the matrices, and stash a map from id to country.
data.forEach(function(d) {
debits[d.creditor.id][d.debtor.id] = d;
credits[d.debtor.id][d.creditor.id] = d;
array[d.creditor.id] = d.creditor;
array[d.debtor.id] = d.debtor;
});
// For each diagram…
svg.each(function(matrix, j) {
var svg = d3.select(this);
// Compute the chord layout.
layout.matrix(matrix);
// Add chords.
svg.selectAll("path.chord")
.data(layout.chords)
.enter().append("svg:path")
.attr("class", "chord")
.style("fill", function(d) { return fill(d.source.value.risk); })
.style("stroke", function(d) { return d3.rgb(fill(d.source.value.risk)).darker(); })
.attr("d", chord)
.append("svg:title")
.text(function(d) { return d.source.value.debtor.name + " owes " + d.source.value.creditor.name + " $" + format(d.source.value) + "B."; });
// Add groups.
var g = svg.selectAll("g.group")
.data(layout.groups)
.enter().append("svg:g")
.attr("class", "group");
// Add the group arc.
g.append("svg:path")
.style("fill", function(d) { return fill(array[d.index].risk); })
.attr("id", function(d, i) { return "group" + d.index + "-" + j; })
.attr("d", arc)
.append("svg:title")
.text(function(d) { return array[d.index].name + " " + (j ? "owes" : "is owed") + " $" + format(d.value) + "B."; });
// Add the group label (but only for large groups, where it will fit).
// An alternative labeling mechanism would be nice for the small groups.
g.append("svg:text")
.attr("x", 6)
.attr("dy", 15)
.filter(function(d) { return d.value > 110; })
.append("svg:textPath")
.attr("xlink:href", function(d) { return "#group" + d.index + "-" + j; })
.text(function(d) { return array[d.index].name; });
});
// Memoize the specified country, computing a unique id.
function country(d) {
return countries[d] || (countries[d] = {
name: d,
id: n++
});
}
// Converts a debit object to its primitive numeric value.
function value() {
return +this.amount;
}
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment