djq
djq

Reputation: 15298

How to make multiple pie charts using D3 and a JS dictionary?

I am trying to adapt the code from Mike Bostock's example of making multiple pie charts. It's extremely concise, but I am struggling to understand one basic piece of the code:

// Define the data as a two-dimensional array of numbers. If you had other
// data to associate with each number, replace each number with an object, e.g.,
// `{key: "value"}`.
var data = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

What is an example of {key: "value"} that makes this work? I've tried

[{key1: 100}, {key2: 200}]

[{key1: 100, key2: 200}]

[{'key1': 100, 'key2': 200}] and a few other permutations.

My goal is to use a json object instead of a data structure like this, but I want to better understand how to construct the correct data structure.

To generate the chart (via the gist) the following code is used:

var m = 10,
    r = 100,
    z = d3.scale.category20c();

var svg = d3.select(".sentiment-pie-chart-1").selectAll("svg")
    .data(data)
  .enter().append("svg:svg")
    .attr("width", (r + m) * 2)
    .attr("height", (r + m) * 2)
  .append("svg:g")
    .attr("transform", "translate(" + (r + m) + "," + (r + m) + ")");

svg.selectAll("path")
    .data(d3.layout.pie())
  .enter().append("svg:path")
    .attr("d", d3.svg.arc()
    .innerRadius(r / 2)
    .outerRadius(r))
    .style("fill", function(d, i) { return z(i); });

Upvotes: 1

Views: 2877

Answers (2)

kavita jadhav
kavita jadhav

Reputation: 162

<html>
<head>
    <title>
        Pie chart
    </title>
<script type="text/javascript" src='d3.v3.min.js' charset='utf-8' ></script>
</head>
    <body>
        <script type="text/javascript">

            var data = [
                [11975,  5871, 8916, 2868],
                [ 1951, 10048, 2060, 6171],
                [ 8010, 16145, 8090, 8045],
                [ 1013,   990,  940, 6907]
            ];

            //For the data above you can convert each data row in array of object.
            //like,

            var newData = data[0].map(function(val){
                return {value : val} ;
            });

            //here you will get  : 

            // var newData = [
            //     {value : 11975} ,
            //     {value : 5871} ,
            //     {value : 8916} ,
            //     {value : 2868} ];

            // You can do same thing for each data row  .

            var width = 1100 , height = 650 , radius = 250 ,
            color = ["#C5AAF5","#FB7374","#A3CBF1","#79BFA1","#F5A352","#94B3C8", "#F9D08B","#B2AC4E","#64BD4F","#C09372"];

            var colorDescriptions = [];

            var svgContainer = d3.select("body") // create svg container
                .append("svg:svg")
                .data([newData])
                .attr("width", width)
                .attr("height", height)
                .append("svg:g")
                .attr("transform", "translate(" + 300 + "," + 300 + ")") ;;

            // Create new svg containier for each element && transform it to diff point.
            var arc = d3.svg.arc() // draw arc of given radius
                .outerRadius(radius);

            var pie = d3.layout.pie() // assign data for pie chart
                .value(function(d) { return d.value; });

            var arcs = svgContainer.selectAll("g.slice") // slice the circle
                .data(pie)   
                .enter()
                .append("svg:g")
                .attr("class", "slice");

            arcs.append("svg:path") // fill color in each slice
                .attr("fill", function(d, i) { return color[i]; } )
                .attr("d", arc)

            arcs.append("svg:text") // write slice information values
                .attr("transform", function(d) {
                d.innerRadius = 0;
                d.outerRadius = radius;
                    return "translate(" + arc.centroid(d) + ")";
                })
                .attr("text-anchor", "middle")
                .text(function(d, i) { return newData[i].value; })
                .style("font-family","monospace")
                .style("fill", "#3f3f3f")
                .style("font-size", "20px");

            var description = svgContainer.append("g").attr("class", "description"); // pie chart description
            var desc_label = description.append("text")
                .attr("class", "description")
                .attr("y", 300)
                .attr("x", 000)
                .text("Pie Chart")
                .style("font-weight", "bold")
                .style("font-size", "20px")
                .style("text-anchor", "middle"); 
        </script>
    </body>
</html>

Upvotes: 1

Lars Kotthoff
Lars Kotthoff

Reputation: 109282

You can use any arbitrary structure (including the ones you've listed) as long as you then also replace the way the pie chart layout extracts the value from this structure. This means that you probably want consistent key names though. For example for the data structure

[{key1: 100}, {key1: 200}]

you would need to define the pie chart layout as follows using the .value() function -- I assume this is your question.

svg.selectAll("path")
   .data(d3.layout.pie().value(function(d) { return d.key1; })
// etc

This would take each element in each array (note that you have 2 nested arrays of objects here) and get the member .key1 to calculate the pie chart fraction.

Upvotes: 2

Related Questions