Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add percentages to the pie chart label in dc.js

I have a pie chart for which I want to add percentages to the label. Here is a jsfiddle of the pie chart and the code is below. Right now the chart shows the actual values. I looked at the dc.js Getting Started and How-To Guide which is an example of a dashboard. It has the chart with percentages in the label. However, when I try to replicate the structure I get an error. For example, when I use the label function like so

.label(function(d) {if(all.value){return d.key + " " + d.value / all.value();}
.renderLabel(true)

in the console it says that all is not defined. Also, the d.key returns nothing as well. I guess my data has a different structure. Help appreciated. Thanks.

HTML

<body>
    <div id='Chart'>
    </div>
</body>

JS

var ndx = crossfilter(data);

var XDimension = ndx.dimension(function (d) {
    return d.Category;
});

var YDimension = XDimension.group();

dc.pieChart("#Chart")
    .width(480).height(300)
    .dimension(XDimension)
    .group(YDimension)
    .label(function(d){return d.value});

dc.renderAll();

Data

var data = [{
    Category: "A",
    ID: "1"
}, {
    Category: "A",
    ID: "1"
}, {
    Category: "A",
    ID: "1"
}, {
    Category: "A",
    ID: "2"
}, {
    Category: "A",
    ID: "2"
}, {
    Category: "B",
    ID: "1"
}, {
    Category: "B",
    ID: "1"
}, {
    Category: "B",
    ID: "1"
}, {
    Category: "B",
    ID: "2"
}, {
    Category: "B",
    ID: "3"
}, {
    Category: "B",
    ID: "3"
}, {
    Category: "B",
    ID: "3"
}, {
    Category: "B",
    ID: "4"
}, {
    Category: "C",
    ID: "1"
}, {
    Category: "C",
    ID: "2"
}, {
    Category: "C",
    ID: "3"
}, {
    Category: "C",
    ID: "4"
}, {
    Category: "C",
    ID: "4"
},{
    Category: "C",
    ID: "5"
}];
like image 452
Koba Avatar asked Aug 08 '14 18:08

Koba


2 Answers

You were close! In cases like this, I'd recommend doing something like the following:

.label(function(d) {
    console.log(JSON.stringify(d));
})

to get a feel for the structure of your data. If you do so, you'll see that key and value are under d.data, so you could have a label like

.label(function(d) {
    return d.data.key + ' ' + d.data.value + '%';
})

If you just want to calculate the fraction of the circle being displayed, you can use the startAngle and endAngle properties.

.label(function(d) {
    return d.data.key + ' ' + Math.round((d.endAngle - d.startAngle) / Math.PI * 50) + '%';
});

(d.endAngle - d.startAngle) will give you the number of radians the slice is displaying, so you can calculate a percentage from there by dividing by the number of radians in a circle.

like image 99
Mike Precup Avatar answered Oct 20 '22 00:10

Mike Precup


.label is the right way to modify BUT pie chart has bug, Check by log on d

.label(d => {
    console.log(d);
    // {
    //  key: 'which you return in dimension',
    //  value: 'ex: 259.91'
    // }
})

Ex, have 6 objs in array, BUT log may just 3 or 4 of them @@ To work around this bug

.on('pretransition', function(chart){
    chart.selectAll('text.pie-slice').text(d => {
        console.log(d);
        // {
        //  data: {
        //      key: 'which you return in dimension',
        //      value: 'ex: 259.91'
        //  },
        //  endAngle: 'xxx',
        //  startAngle: 'yyy'
        // }
    })
})

d obj inside text()

By this way we can log enough 6 objs in array The label text is return val inside text(d => {})

chart.selectAll('text.pie-slice').text(function(d){
    let label = d.data.key;
    return label + ': ' + Number(d.data.value).toFixed(2);
})

//Or play with percentage
chart.selectAll('text.pie-slice').text(function(d){
    return d.data.key + ' ' + dc.utils.printSingleValue((d.endAngle - d.startAngle) / (2*Math.PI) * 100) + '%';
})
like image 40
Anh Le Hoang Avatar answered Oct 19 '22 22:10

Anh Le Hoang