Add percentages to the pie chart label in dc.js
Asked Answered
D

3

5

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"
}];
Dhu answered 8/8, 2014 at 18:27 Comment(0)
H
10

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.

Hesta answered 8/8, 2014 at 18:50 Comment(4)
the console.log(JSON.stringify(d)) is very useful. thanks. Yet, I have to calculate the percentages because as of right now I have just the counts. Even using the console log I did not find the all.value() in the data which I need to get the percentages unless there is another way. You answer my question about how to concatenate keys and values, but the percentages part is the most vital one.Dhu
Edited to include how to check what percent of the circle is showing.Hesta
Wow thats actually a smart solution. What I did was I just used the length of the data object and then divided by it, but your way is more reliable. Thanks. Hopefully, they will turn it into a function or something, so its less work.Dhu
.label(function(d) does not have d.data it only has the d.keyYonkers
S
1

.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) + '%';
})
Synaesthesia answered 12/1, 2017 at 5:5 Comment(0)
Z
0

Indeed, it does not have d.data. Instead I use the .renderlet() : :

.renderlet(function(chart){
        chart.selectAll('text.pie-slice').text( function(d) {
        return d.data.key + ' ' + dc.utils.printSingleValue((d.endAngle - d.startAngle) / (2*Math.PI) * 100) + '%';
        })
    })
Zipper answered 18/8, 2016 at 6:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.