block by curran d0a42741ce0cf6cdc3ab

Sized Donut Charts

Full Screen

A small multiples visualization of donut charts showing the breakdown of religions for the largest 5 countries.

Note that area is proportional to population, because the area of each pie corresponds to the population of each country (the sum of all religions). This makes the visualization more “honest” than the fixed size Donut Chart Small Multiples.

forked from curran‘s block: Sized Pie Charts

Thanks to enjalot for the idea to size each donut.

web counter

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>D3 Example</title>
    <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/d3-legend/1.1.0/d3-legend.js"></script>
    <link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
    <style>
    
      .axis text {
        font-family: 'Open Sans', sans-serif;
        font-size: 21pt;
      }

      .axis path, .axis line {
        fill: none;
        stroke: #000;
        shape-rendering: crispEdges;
      }

      .color-legend text {
        font-family: 'Open Sans', sans-serif;
        font-size: 17pt;
      }

    </style>
  </head>
  <body>
    <script>

      var outerWidth = 960;
      var outerHeight = 500;
      var margin = { left: 95, top: 0, right: 64, bottom: 297 };

      var xColumn = "country";
      var colorColumn = "religion";
      var areaColumn = "population";
      var radiusMax = 95;

      var innerWidth  = outerWidth  - margin.left - margin.right;
      var innerHeight = outerHeight - margin.top  - margin.bottom;

      var svg = d3.select("body").append("svg")
        .attr("width",  outerWidth)
        .attr("height", outerHeight);
      var g = svg.append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
      var xAxisG = g.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + innerHeight + ")");

      var colorLegendG = svg.append("g")
        .attr("class", "color-legend")
        .attr("transform", "translate(415, 255)");

      var xScale = d3.scale.ordinal().rangePoints([0, innerWidth]);
      var radiusScale = d3.scale.sqrt().range([0, radiusMax]);
      var colorScale = d3.scale.category10();

      var xAxis = d3.svg.axis().scale(xScale).orient("bottom")
        .outerTickSize(0);

      var pie = d3.layout.pie();
      var arc = d3.svg.arc();
      arc.innerRadius(0);

      var colorLegend = d3.legend.color()
        .scale(colorScale)
        .shapePadding(3)
        .shapeWidth(25)
        .shapeHeight(25)
        .labelOffset(4);

      function render(data){

        var nested = d3.nest()
          .key(function (d){ return d[xColumn]; })
          .entries(data);
        
        // Compute sums for the radius field,
        // for setting the size of each pie.
        nested.forEach(function (xEntry){
          xEntry.areaColumnSum = d3.sum(xEntry.values, function (d){
            return d[areaColumn];
          });
        });

        xScale.domain(nested.map( function (d){ return d.key; }));
        colorScale.domain(nested[0].values.map(function (d){ return d[colorColumn]; }));
        pie.value(function(d) { return d[areaColumn]; });
        
        radiusScale.domain([
          0,
          d3.max(nested, function (xEntry){
            return xEntry.areaColumnSum;
          })
        ]);

        var pies = g.selectAll(".pie").data(nested);
        pies.enter().append("g").attr("class", "pie");
        pies.attr("transform", function (d){
          var x = xScale(d.key);
          return "translate(" + x + "," + innerHeight / 2 + ")";
        });
        pies.exit().remove();

        var slices = pies.selectAll("path").data(function (d){
          return pie(d.values);
        });

        slices.enter().append("path");
        slices
          .attr("d", function (d, i, j){
            var r = radiusScale(nested[j].areaColumnSum);
            arc.outerRadius(r);
            arc.innerRadius(r / 2);
            return arc(d);
          })
          .attr("fill", function (d){ return colorScale(d.data[colorColumn]); });
        slices.exit().remove();

        xAxisG.call(xAxis);
        colorLegendG.call(colorLegend);
      }

      function type(d){
        d.name = "World";
        d.population = +d.population;
        return d;
      }

      d3.csv("religionByCountryTop5.csv", type, render);

    </script>
  </body>
</html>

religionByCountryTop5.csv

country,religion,population
China,Christian,68410000
China,Muslim,24690000
China,Unaffiliated,700680000
China,Hindu,20000
China,Buddhist,244130000
China,Folk Religions,294320000
China,Other Religions,9080000
China,Jewish,0
India,Christian,31130000
India,Muslim,176190000
India,Unaffiliated,870000
India,Hindu,973750000
India,Buddhist,9250000
India,Folk Religions,5840000
India,Other Religions,27560000
India,Jewish,10000
USA,Christian,243060000
USA,Muslim,2770000
USA,Unaffiliated,50980000
USA,Hindu,1790000
USA,Buddhist,3570000
USA,Folk Religions,630000
USA,Other Religions,1900000
USA,Jewish,5690000
Indonesia,Christian,23660000
Indonesia,Muslim,209120000
Indonesia,Unaffiliated,240000
Indonesia,Hindu,4050000
Indonesia,Buddhist,1720000
Indonesia,Folk Religions,750000
Indonesia,Other Religions,340000
Indonesia,Jewish,0
Brazil,Christian,173300000
Brazil,Muslim,40000
Brazil,Unaffiliated,15410000
Brazil,Hindu,0
Brazil,Buddhist,250000
Brazil,Folk Religions,5540000
Brazil,Other Religions,300000
Brazil,Jewish,110000