Skip to main content
A pie chart is a single stacked-fill bar bent around a circle: geom.bar({ position: 'fill' }) under coord.polar({ theta: 'y' }). Each slice’s angle is proportional to its value. Add an innerRadius and it becomes a donut — a pie with the centre cut out. Both work best for a small number of parts of a whole.

Pie

Map the slice category to color, the value to y, and leave x empty so all slices share one band:

Donut

A donut is the same recipe with an innerRadius on the polar coord. The hole leaves room for a headline number, and the thinner ring can read more cleanly than a full pie:
innerRadius is a fraction of the outer radius — 0.55 cuts the hole just past the halfway point. Larger values give a thinner ring. The hole is the natural home for a headline number:
position: 'center' needs a non-zero innerRadius — on a full pie there is no hole to sit in.

Where the first slice starts

coord.polar takes a startAngle in degrees, defaulting to 0. It rotates the whole ring, which is how you put a dominant slice at a particular clock position:

Slice labels

Turn on data labels to print each slice’s value or share. On polar bars, showCategoryLabels prefixes the category:

Separated wedges

A border in the chart’s background color leaves a crisp gap between wedges. Borders are paint, so they come from the stylesheet:
The border is the lever for this, not the scale: every slice is a segment of one stacked bar, so the segments meet edge to edge and there is no band gap between them to widen.

Rounded wedges

Wedges carry the bar geom’s borderRadius, a named token the polar renderer resolves against each wedge’s radial span. The built-in default is 'sm', so wedge corners are already slightly softened: