Health Infobase Design Manual
Table of contents
Pie chart and doughnut chart
A pie chart is a visual representation of data of the relative sizes or proportions of different data points.
A doughnut chart is similar to a pie chart, but it has a hole in the centre, which makes it easier to compare the proportions of different data points.
On this page
When to use
- To show the relative size or proportion of different data points
- To compare the proportions of different data points
- To illustrate a “part-to-whole” relationship
Examples
- A pie chart showing how much is spent on healthcare by different categories, such as hospital care, prescription drugs, and preventive care
- A doughnut showing the proportion of deaths due to different causes in a population
What to avoid
- Don’t use pie charts or doughnut charts to show data that does not have a clear numeric value
- Don’t use pie charts or doughnut charts to show data with different units or different scales
- Pie charts or doughnut charts are usually hard to read if there are too many categories, so avoid using pie charts with more than 5-6 categories
- In most cases, there are better alternatives to Pie chart and doughnut charts (such as bar graphs or stacked bar graphs)
Design and code
HTML
<!-- Add D3 library in the head section -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- Add a div in the section where you want the graph -->
<div id="pieGraph"></div>
JS
<script>
const width = 650, height = 650, margin = 100;
// radius of the pie graph is half the width or half the height
const radius = Math.min(width, height) / 2 - margin;
const svg = d3.select("#pieGraph")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", `translate(${width/2},${height/2})`);
// dummy fruit data
const data = {Apples: 26, Oranges: 12, Pears:33, Bananas:8, };
const color = d3.scaleOrdinal()
.domain(["Apples", "Oranges", "Pears", "Bananas",])
.range(d3.schemeDark2);
// compute the position of each group
const pieGraph = d3.pie()
.sort(null)
.value(d => d[1]);
const pieData = pieGraph(Object.entries(data));
const arc = d3.arc()
// size of the inner hole (to get a pie chart instead od a doughnut chart, change inner radius to 0)
.innerRadius(radius * 0.5)
.outerRadius(radius * 0.8);
// arc for label positioning
const outerArc = d3.arc()
.innerRadius(radius * 0.9)
.outerRadius(radius * 0.9);
// build the pie chart path
svg
.selectAll('path')
.data(pieData)
.join('path')
.attr('d', arc)
.attr('fill', d => color(d.data[1]))
.attr("stroke", "white")
.style("opacity", 0.7)
.style("stroke-width", "2px");
// Add lines for labels
svg
.selectAll('polyline')
.data(pieData)
.join('polyline')
.attr("stroke", "black")
.style("fill", "none")
.attr("stroke-width", 1.3)
.attr('points', function(d) {
const position1 = arc.centroid(d);
const position2 = outerArc.centroid(d);
const position3 = outerArc.centroid(d);
const middleAngle = d.startAngle + (d.endAngle - d.startAngle) / 2;
position3[0] = radius * 0.95 * (middleAngle < Math.PI ? 1 : -1);
return [position1, position2, position3]
})
// Add the polylines between chart and labels:
svg
.selectAll('text')
.data(pieData)
.join('text')
.text(d => d.data[0])
.attr('transform', function(d) {
const position = outerArc.centroid(d);
const middleAngle = d.startAngle + (d.endAngle - d.startAngle) / 2
position[0] = radius * 0.99 * (middleAngle < Math.PI ? 1 : -1);
return `translate(${position})`;
})
.style('text-anchor', function(d) {
const middleAngle = d.startAngle + (d.endAngle - d.startAngle) / 2
return (middleAngle < Math.PI ? 'start' : 'end')
});
</script>
Content and design guidelines
- Try to limit the number of categories to avoid confusion
- Use colour wisely to differentiate the different categories
- Consider having the labels directly within the areas of the chart, if possible
- Follow the general design guidelines
Accessibility guidelines
- Provide a data table with the chart
- If the pie chart or doughnut chart tells a clear story, include that story in the alt text. For example, if the graph shows that category has a much higher value than the others, spell that out in the alt text
- Follow the general accessibility guidelines
- Date modified: