Skip to content

Instantly share code, notes, and snippets.

@mbostock
Last active January 12, 2020 03:40
Show Gist options
  • Save mbostock/1308257 to your computer and use it in GitHub Desktop.
Save mbostock/1308257 to your computer and use it in GitHub Desktop.
The Euro Debt Crisis

I enjoyed an analysis of the Euro debt crisis by Bill Marsh of the New York Times, but I was curious to see how the data would look in D3’s chord layout. Chord layouts are great for showing asymmetric relationships among a group of entities—in this case, debt owed by countries.

For this visualization, I decided to create two chord diagrams. The diagram on the left emphasizes how much each country lends; 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; the United States has by far the largest debt, nearly three times the size of the next-largest debtor, Britain!

creditor debtor amount risk
Britain France 22.4 1
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">
var w = 480,
h = 500,
r1 = Math.min(w, h) / 2 - 4,
r0 = r1 - 20;
var format = d3.format(",.3r"),
debts = [],
credits = [];
var layout = d3.layout.chord()
.sortGroups(d3.descending)
.sortSubgroups(d3.descending)
.sortChords(d3.descending)
.padding(.04);
var fill = d3.scale.ordinal()
.domain([0, 1, 2])
.range(["#DB704D", "#D2D0C6", "#F8EDD3"]);
var arc = d3.svg.arc()
.innerRadius(r0)
.outerRadius(r1);
var chord = d3.svg.chord()
.radius(r0);
var svg = d3.select("body").selectAll("svg")
.data([debts, credits])
.enter().append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
d3.csv("debt.csv", function(data) {
var countries = {},
array = [],
n = 0;
// Compute the row number for each unique country.
data.forEach(function(d) {
d.creditor = country(d.creditor);
d.debtor = country(d.debtor);
d.debtor.risk = d.risk;
d.valueOf = value;
});
// Initialize a square matrix of debts and credits.
for (var i = 0; i < n; i++) {
debts[i] = [];
credits[i] = [];
for (var j = 0; j < n; j++) {
debts[i][j] = 0;
credits[i][j] = 0;
}
}
// Populate the matrices.
data.forEach(function(d) {
debts[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 matrix…
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");
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."; });
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; });
});
function country(d) {
return countries[d] || (countries[d] = {
name: d,
id: n++
});
}
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