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 ageom.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 datetimex 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 forgeom.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:
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:
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 keepstheta: '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 withtheta: '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:
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:
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 tox, so both axes render by default. Turn the x axis off when the legend already names the spokes:
Related
- Styling — fill opacity, marker size, corner radius and per-layer scoping
- Coordinate systems — the polar plane,
theta,startAngleandinnerRadius - Pie & donut — the
theta: 'y'parts-of-a-whole family - Chart types overview — geoms, positions and the full recipe list

