Reputation: 2307
I am getting some data which are in range of 0 to 100, so I want to group them in different group say [0, 50, 80, 100] and plot pie chart with different color for each group of data like
(0-50 red, 51-80 yellow, 81-100 green).
function drawPieChart(data) {
var height = 500;
var width = 500;
var radius = Math.min(width, height)/4;
var canvas = d3.select('#divId').append('svg')
.attr('width', width).attr('height', height);
var arc = d3.arc().outerRadius(radius - 10).innerRadius(0);
var pie = d3.pie().sort(null).value(function (data) {
return data.value;
});
var color = d3.scaleOrdinal().domain([0,50,80,100]).range(['red', 'orange', 'green']);
var arcs = canvas.selectAll('arc')
.data(pie(data))
.enter()
.append('g')
.attr('class', 'arc')
.append('path')
.attr('d', arc).attr('transform', 'translate(' + height /4 + ',' + width /4 +')')
.style('fill', function (data) {
//**my silly attempt to achieve this. unsuccessful though**
/*if(data.value > 90){
return arc.apply('fill', 'blue');
}else if(data.value > 70 && data.value <= 90){
return arc.apply('fill', 'green');
}else if(data.value > 50 && data.value <= 70){
return arc.apply('fill', 'yellow');
}else{
return arc.attr('fill', 'red');
}*/
return color(data); // this function is resulting the whole graph of one color, whichever defind first in range (here red)
})
}
Upvotes: 0
Views: 1380
Reputation: 517
You can use d3.scaleThreshold, docs here: https://github.com/d3/d3-scale#threshold-scales.
I used a pie chart example bl.ock from here, to get this codepen: https://codepen.io/anon/pen/Yjwryz?editors=0011, and here's the code you would be interested in:
var threshold = 0.00000000000001;
var groupDomain = [
50 + threshold, // Red group x: (x <= 50)
70 + threshold, // Yellow group x: (50 < x <= 70)
90 + threshold, // Green group x: (70 < x <= 90)
100 // Blue group x: (x > 90)
];
var color = d3.scaleThreshold()
.domain(groupDomain)
.range(['red', 'yellow', 'green', 'blue']);
...
...
.style("fill", function(d) {return color(d.data); });
Note, I added a small error threshold to the group domains you wanted since I think .scaleThreshold is set up to work up until a value in the domain, i.e. < 50 not <= 50. I'm not sure though I didn't check the docs.
Edit: Sorting the data array with '.sort' will take care of the problem you're having with unordered data:
var data = [
100, 20, 30, 40, 50, // Red group
55, 10, 65, 70, // Yellow group
75, 80, 90, // Green group
95, 100 // Blue group
].sort(function (a, b) {
return a - b
});
Updated codepen: https://codepen.io/anon/pen/Yjwryz?editors=0011
Second edit: I attempted what I believe you were referring to in your comment by grouping all of the data between the specified ranges and then basing the arc segment on the amount of data points which fall in each specified range. Here's a codepen: https://codepen.io/anon/pen/wxMNgg?editors=0010
The relevant code for this change:
var color = d3.scaleThreshold()
.domain(groupDomain)
.range(['red', 'yellow', 'green', 'blue']);
var groupedData = [];
data.forEach(function (e) {
var group = color.invertExtent(color(e))[1];
group = (group == 100) ? group : group - threshold;
var groupIndex = groupedData.findIndex(d => d.group == group)
if (groupIndex != -1) {
groupedData[groupIndex].count += 1;
} else {
groupedData.push({
group : group,
count : 1
});
}
});
Upvotes: 1
Reputation: 28653
You need to group your data before creating the Pie chart
var dataByGroup = d3.nest()
.key(function(d) { if (d<=50) return "50"; if (d<=80) return "80"; return "100"; })
.rollup(function(v) { return v.length; })
.entries(data);
Upvotes: 0