Did you know that you can navigate the posts by swiping left and right?

D3 Pie Chart

July 02, 2017, July 02, 2017 | Comments

category: VISUALIZATION
d3 html css javascript

Pie chart is probably one of the simplest statistical charts used to describe the numerical proportion by dividing the whole circles into slices. D3 uses d3.pie() function, also under d3-shape module, to calculate angles to represent a tabular dataset which are later passed to arc generator.

One of the most interesting pie charts I have ever seen is the Pyramid Pie Chart. For illustration purposes, I will use D3 to represent this pie chart again.

One of the most obvious change in the overall setting is the new function to define the radius of circle for the pie chart.

var radius = Math.min(width, height) / 2;

Then, d3.pie() function is called to start a pie generator followed by value() function to use pop in the data generated to represent the arc.

var pie = d3.pie().sort(null)
	.value(function(d) { return d.pop; })(data);

As introduced above, d3.arc() function is used to define the outer and inner radius of the circle and I also use start and end angle to “rotate” the pie for showing the sky above the pyramid.

var arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(0)
    .startAngle(function(d) { return d.startAngle + Math.PI*1.2; })
    .endAngle(function(d) { return d.endAngle + Math.PI*1.2; });

By the way, if we change the innerRadius() from 0 to other positive number, it would eventually show a doughnut chart.

The final key code the show the pie chart is to pass pie function to arc.

var pyramid = g.selectAll(".arc")
    .data(pie)
    .enter()
    .append("g")
    .attr("class", "arc");

Here is the full code:

<style>
svg {
    width: 100%;
    height: 100%;
    position: center;
}

#pyramid {
   background-color: lightgrey;
}

</style>

<svg id="pyramid" width="950" height="500"></svg>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var margin = {top: 30, right: 30, bottom: 30, left: 30};
var width = document.getElementById("pyramid").getBoundingClientRect().width-100;
var height = 400;
var radius = Math.min(width, height) / 2;

var color = d3.scaleOrdinal(["#0095D9", "#9C9536", "#F5E837"]);

var data = [
            {"type":"Sky","pop":0.75},
            {"type":"Shady side of pyramid","pop":0.07},
            {"type":"Sunny side of pyramid","pop":0.18}
            ];

var g = d3.select("#pyramid")
        .append("g")
        .attr("transform", "translate(" + width / 1.8 + "," + height / 1.6 + ")");

var pie = d3.pie().sort(null)
	.value(function(d) { return d.pop; })(data);
    
var arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(0)
    .startAngle(function(d) { return d.startAngle + Math.PI*1.2; })
    .endAngle(function(d) { return d.endAngle + Math.PI*1.2; });
    
var pyramid = g.selectAll(".arc")
    .data(pie)
    .enter()
    .append("g")
    .attr("class", "arc");

pyramid.append("path")
	.attr("d", arc)
	.style("fill", function(d) { return color(d.data.type);});

var legend = g.append("g")
      .attr("class", "legend")
      .attr("font-family", "sans-serif")
      .attr("font-size", 20)
      .attr("text-anchor", "start")
      .attr("transform", "translate(-40,100)")
      .selectAll("g")
      .data(pie)
      .enter().append("g")
      .attr("transform", function(d, i) { return "translate(20," + i * 20 + ")"; });  
      
legend.append("text")
      .attr("x", radius + 10)
      .attr("y", 9.5)
      .attr("dy", "0.32em")
      .text(function(d) { return d.data.type; });
      
legend.append("rect")
      .attr("x", radius - 10)
      .attr("width", 19)
      .attr("height", 19)
      .attr("fill", function(d) { return color(d.data.type);});

</script>

I also put this example under my Blocks.

Reference:

(1). D3 API Reference, https://github.com/d3/d3/blob/master/API.md.
(2). Multi-Series Line Chart, https://bl.ocks.org/mbostock/3884955.