Skip to content

Instantly share code, notes, and snippets.

@mbostock
Forked from mbostock/.block
Last active February 9, 2016 00:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mbostock/1305337 to your computer and use it in GitHub Desktop.
Save mbostock/1305337 to your computer and use it in GitHub Desktop.
Pie Multiples with Nesting
license: gpl-3.0

An example of multiple pie (donut) charts created with D3. The data is represented as a tabular array of objects; each row in the table is mapped to an arc, and rows are grouped into pie charts using d3.nest.

origin carrier count
ATL 9E 5
ATL AA 22
ATL CO 11
ATL DL 360
ATL EV 245
ATL F9 3
ATL FL 241
ATL MQ 2
ATL NW 14
ATL OH 12
ATL OO 11
ATL UA 8
ATL US 9
ATL XE 3
ATL YV 7
DFW 9E 2
DFW AA 448
DFW AS 3
DFW CO 10
DFW DL 10
DFW F9 4
DFW FL 7
DFW MQ 254
DFW NW 5
DFW OH 3
DFW OO 5
DFW UA 13
DFW US 18
DFW XE 4
ORD AA 203
ORD AS 4
ORD B6 7
ORD CO 14
ORD DL 10
ORD MQ 253
ORD NW 17
ORD OH 9
ORD OO 125
ORD UA 228
ORD US 19
ORD XE 3
ORD YV 60
SFO AA 34
SFO AS 14
SFO B6 5
SFO CO 14
SFO DL 12
SFO F9 4
SFO FL 2
SFO HA 1
SFO MQ 5
SFO NW 10
SFO OO 110
SFO UA 125
SFO US 20
SFO WN 24
SFO XE 5
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
text-align: center;
}
svg {
font: 10px sans-serif;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
// Define the margin, radius, and color scale. Colors are assigned lazily, so
// if you want deterministic behavior, define a domain for the color scale.
var m = 10,
r = 100,
z = d3.scale.category20c();
// Define a pie layout: the pie angle encodes the count of flights. Since our
// data is stored in CSV, the counts are strings which we coerce to numbers.
var pie = d3.layout.pie()
.value(function(d) { return +d.count; })
.sort(function(a, b) { return b.count - a.count; });
// Define an arc generator. Note the radius is specified here, not the layout.
var arc = d3.svg.arc()
.innerRadius(r / 2)
.outerRadius(r);
// Load the flight data asynchronously.
d3.csv("flights.csv", function(error, flights) {
if (error) throw error;
// Nest the flight data by originating airport. Our data has the counts per
// airport and carrier, but we want to group counts by aiport.
var airports = d3.nest()
.key(function(d) { return d.origin; })
.entries(flights);
// Insert an svg element (with margin) for each airport in our dataset. A
// child g element translates the origin to the pie center.
var svg = d3.select("body").selectAll("div")
.data(airports)
.enter().append("div") // http://code.google.com/p/chromium/issues/detail?id=98951
.style("display", "inline-block")
.style("width", (r + m) * 2 + "px")
.style("height", (r + m) * 2 + "px")
.append("svg")
.attr("width", (r + m) * 2)
.attr("height", (r + m) * 2)
.append("g")
.attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");
// Add a label for the airport. The `key` comes from the nest operator.
svg.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.key; });
// Pass the nested per-airport values to the pie layout. The layout computes
// the angles for each arc. Another g element will hold the arc and its label.
var g = svg.selectAll("g")
.data(function(d) { return pie(d.values); })
.enter().append("g");
// Add a colored arc path, with a mouseover title showing the count.
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return z(d.data.carrier); })
.append("title")
.text(function(d) { return d.data.carrier + ": " + d.data.count; });
// Add a label to the larger arcs, translated to the arc centroid and rotated.
g.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
.text(function(d) { return d.data.carrier; });
// Computes the label angle of an arc, converting from radians to degrees.
function angle(d) {
var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
return a > 90 ? a - 180 : a;
}
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment