Skip to main content
Radial charts bend the plane into a circle with coord.polar, just like pie & donut, but here the category sweeps around the circle instead of the value. With theta: 'x', each category takes a spoke and its value grows outward along the radius. The geom then sets the shape: geom.line() traces a radar, geom.area() fills it, geom.bar() draws a rose. With theta: 'y', the value sweeps the angle instead, and each category becomes its own concentric track — a radial bar. They read best for a small, fixed set of categories compared across a few groups: a skills profile, a weekly cycle, activity by hour.

Radar

A radar (or spider) chart is a geom.line() under coord.polar({ theta: 'x' }). Map the axis category to x, the value to y, and a group column to color. Two scale settings carry the chart. A discrete x scale gives each category an evenly spaced spoke. domainMin: 0 on y is all but required for a line: it puts zero at the center of the circle, so the radius stays proportional to the value. Without it the domain starts at the data minimum, which lands at the center and exaggerates the differences. An area or bar holds zero on its own. A non-interactive geom.point() layer marks each vertex:

Time around the circle

A datetime x scale in place of the discrete one turns the radar into a clock or a calendar. See Coordinate systems for how the turn is divided:

Filled radar

Swap the line for geom.area({ position: 'identity' }) to fill each group’s polygon. Keep position: 'identity' so the areas overlap at their true values rather than stacking; the vertex points still sit on top:
Area fills draw at fillAlpha: 0.3. With more than two or three groups they still obscure each other. Use the outline radar above, or take the fill down further through the stylesheet:
The vertex dots draw at the built-in size: 8, which is heavy for a radar. Give the point layer an id and scope a style entry to it:

Rose / coxcomb

A rose (or coxcomb) chart keeps theta: 'x' but draws bars instead of a line: each category is a wedge, and the value sets how far it reaches. Map a group to color and pick a position: dodge splits each wedge into side-by-side petals, stack grows the groups outward along the radius:
params.width sets a petal’s angular thickness as a fraction of its band, in (0, 1]. Under polar it defaults to 1, so neighboring petals touch; drop it to open a gap between wedges.

Radial bar

A radial bar (or race-track) chart puts the value back on the angle with theta: 'y': each category is its own concentric track and the value sweeps around it. An innerRadius opens the center so the innermost track is not crushed into a point. Stack the groups to read each track as consecutive colored segments:
Here params.width is the radial thickness of each track. cornerRadius: 'full' gives a racetrack its capsule ends by rounding each arc to half its radial span:
On a stacked track only the outer corners of the whole arc round, so the segments inside it stay flush. A border in the background color separates them instead:

Where the first spoke lands

coord.polar takes a startAngle in degrees, 0 by default. On a rose it decides which spoke sits at the top; on a racetrack, where every arc starts:

Axes

Unlike a pie or donut, these charts map a real column to x, so both axes render by default. Turn the x axis off when the legend already names the spokes: