Search code examples
javascriptd3.jsnestedpie-chart

Using d3.nest to create a pie chart


I have an assortment of data, and I have used it to create a donut chart. I want to make a pie chart using a breakdown of the data, which I've acquired using d3.nest to subdivide the data I had (it was currently in 3 categories: nest breaks it down into 129). Basically, I have Olympic data based on medals awarded, and I want to subdivide the data on interaction into which sports they were earned in.

I'm just not sure how to use nested data to create a pie chart, particularly if the keys are variable. I'll include my implementation for the donut chart.

  var pie = d3.pie();

  // color based on medal awarded
  // order: gold, silver, bronze
  var color = d3.scaleOrdinal()
    .range(['#e5ce0c', '#e5e4e0', '#a4610a']);

  var arcs = d3.select(svg).selectAll("g.arc")
    .data(pie(data))
    .enter()
    .append("g")
    .attr("class", "arc")
    .attr("transform", "translate(" + (w/2) + "," + ((h-25)/2) + ")");

  arcs.append("path")
  .attr("fill", function(d, i) {
    return color(i);
  })
  .attr("d", arc)
  .attr("stroke", "white")
  .style("stroke-width", "0.5px")
  .on('mouseover', function(d) {
    d3.select(this).attr('opacity', .7);

  })
  .on('mouseleave', function(d) {
    d3.select(this).attr('opacity', 1);
  });

  // title
  d3.select(svg).append('text')
    .attr('x', function(d) {
      return ((w/2) - 85);
    })
    .attr('y', '20')
    .text(function(d) {
      return ('Medal breakdown for ' + country);
    })
    .attr('font-size', '16px');

  arcs.append("text")
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("text-anchor", "middle")
    .text(function(d) {
      return d.value;
    });

Solution

  • Can you please confirm is this the format of data you have ?

    Please find the code below and let me know if you have any doubt.

    var w = 400;
    var h = 400;
    var r = h/2;
    var color = d3.scale.category20c();
    
    var data = [
    {name:"football", medal:1},
    {name:"hockey", medal:2},
    {name:"cricket", medal:3},
    {name:"tennis", medal:4},
    {name:"table tennis", medal:5},
    ];
    
    
    var vis = d3.select('#chart').append("svg:svg").data([data]).attr("width", w).attr("height", h).append("svg:g").attr("transform", "translate(" + r + "," + r + ")");
    var pie = d3.layout.pie().value(function(d){return d.medal;});
    
    // declare an arc generator function
    var arc = d3.svg.arc().outerRadius(r);
    
    // select paths, use arc generator to draw
    var arcs = vis.selectAll("g.slice").data(pie).enter().append("svg:g").attr("class", "slice");
    arcs.append("svg:path")
        .attr("fill", function(d, i){
            return color(i);
        })
        .attr("d", function (d) {
            // log the result of the arc generator to show how cool it is :)
            return arc(d);
        });
    
    // add the text
    arcs.append("svg:text").attr("transform", function(d){
    			d.innerRadius = 0;
    			d.outerRadius = r;
        return "translate(" + arc.centroid(d) + ")";}).attr("text-anchor", "middle").text( function(d, i) {
        return data[i].name;}
    		);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.15/d3.min.js"></script>
    <div id="chart"></div>