Lattice Grid Buy a licence

chart gallery

Polar Charts: Rose, Radial Bar and Polar Scatter

Three ways to put a measure round a circle: a Nightingale rose, a radial bar and a polar scatter. Each one below is drawn live by the grid, next to the code that draws it.

Theme All chart types

Polar area chart (Nightingale rose)

A polar area chart, also called a Nightingale rose, gives every category the same slice of the circle and lets the measure decide how far the wedge reaches. It suits anything that repeats on a cycle, such as support tickets by month, where the eye wants to see the busy season as a shape. The radius is area-true by default, so a value four times another reaches twice as far and the picture never overstates a peak. It follows the grid’s filter, has a legend, tooltips and keyboard stops, and carries an accessible data table.

Loading a live chart…

The code

createChart({
  grid,
  container,
  type: 'polarArea',
  x: 'month',
  y: 'tickets',
  title: 'Support tickets by month',
});

Options used: type: 'polarArea', x, y

Sample data
({
  columns: [
    { field: 'month', title: 'Month' },
    { field: 'tickets', title: 'Tickets', type: 'number' },
  ],
  rows: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'].map((month, i) => ({
    id: i,
    month,
    tickets: [118, 96, 124, 140, 163, 189, 205, 198, 171, 150, 132, 177][i],
  })),
})

Radial bar chart

A radial bar chart draws one ring per category, innermost out, each ring an arc whose sweep is its value against the maximum. It packs a ranked comparison into a small round space, which makes it a good fit for a dashboard tile showing progress, completion or share of target for a handful of teams. A faint full track sits behind every ring so the gap to the goal is as visible as the bar, and rings can be ordered by value. Several measures sit as adjacent rings or end to end in one ring.

Loading a live chart…

The code

createChart({
  grid,
  container,
  type: 'radialBar',
  x: 'team',
  y: 'score',
  max: 100,
  polar: { sort: 'desc' },
  title: 'Onboarding complete (%)',
});

Options used: type: 'radialBar', polar, max

Sample data
({
  columns: [
    { field: 'team', title: 'Team' },
    { field: 'score', title: 'Onboarding complete (%)', type: 'number' },
  ],
  rows: [
    { id: 1, team: 'Sales', score: 92 },
    { id: 2, team: 'Support', score: 81 },
    { id: 3, team: 'Platform', score: 74 },
    { id: 4, team: 'Design', score: 66 },
    { id: 5, team: 'Finance', score: 58 },
  ],
})

Polar scatter chart

A polar scatter chart places each row by an angle and a distance from the centre, so direction and size read together. Use it for anything with a bearing or a time of day: wind readings by compass heading, arrivals by hour, or alerts by day of week. The angle column can be degrees, a category spread round the circle, or a periodic time. Clicking a dot selects its row in the grid, and dragging a band selects every row whose dot lies inside it, so the chart is also a way of picking rows.

Try it. Drag across the chart to select the readings in a band, and the matching rows highlight in the grid.

Loading a live chart…

The code

createChart({
  grid,
  container,
  type: 'polarScatter',
  x: 'bearing',
  y: 'speed',
  polar: { angle: 'degrees' },
  brush: 'select',
  selection: true,
  title: 'Wind by bearing',
});

Options used: type: 'polarScatter', polar, brush

Sample data
({
  columns: [
    { field: 'bearing', title: 'Bearing (degrees)', type: 'number' },
    { field: 'speed', title: 'Speed (knots)', type: 'number' },
  ],
  rows: [10, 25, 40, 55, 70, 85, 100, 115, 130, 145, 160, 175, 190, 205, 220, 235, 250, 265, 280, 295, 310, 325, 340, 355].map((bearing, i) => ({
    id: i,
    bearing,
    speed: Math.round(8 + 6 * Math.sin((bearing - 60) * Math.PI / 180) + (i % 5) * 1.5),
  })),
})

Every chart type, live → The charts API reference → How a chart binds to a grid →