Docs / Build Workflow

Visualization — pie

When to use pie

Pie is the right choice for part-of-whole composition when the number of slices is small (typically ≤ 6) and proportional weight matters. Use the donut variant when you want to free the chart center for an inner label or a related KPI; use the rose variant for an alternative encoding where slice angle is fixed but radius reflects the value.

Use bar with chart.stack: percent instead when the categories are many, or when you want to compare composition across multiple groups. Use grid when the audience needs the actual percentages in tabular form.

Mapping

  • mapping.x — required. String field used as the slice name and the legend label.
  • mapping.y — required. Numeric field that drives the slice angle.
mapping:
  x: status
  y: order_count

Slice colors come from the platform palette in query order. To control order, sort in the underlying Malloy query.

chart shortcuts

The chart block is typed and closed.

  • chart.variant"pie" (default), "donut", or "rose". Donut adds an inner radius (free center); rose switches to a rose-area layout where slice angle is uniform and radius encodes the value.
  • chart.inner_radius — number (pixels) or string (e.g. "55%"). Use with variant: donut; the larger the inner radius, the thinner the donut ring.
  • chart.outer_radius — number or string.
  • chart.slice_border_radius — pixels. Rounded corners on slices for a softer look.
  • chart.show_value_labels — boolean. Turns slice labels on. Style them with chart.label below.
  • chart.cross_filter — boolean, default true.
  • chart.height — pixel height of the viz container.

Pass-through fields (1:1 with the underlying chart):

  • chart.center — center of the pie. Array [x, y] of percent strings (e.g. ["50%", "50%"]) or pixel numbers.
  • chart.start_angle — degrees. Default 90.
  • chart.min_angle — degrees. Minimum angle for tiny slices to remain visible.
  • chart.rose_type — when using a rose layout: "radius" or "area".

Slice labels

chart.label is an object that styles slice labels when chart.show_value_labels is on:

  • position"inside", "outside", "top", "bottom", "left", "right", plus the "insideLeft" / "insideRight" variants.
  • rotate — degrees, between -90 and 90.
  • color, font_size, font_weight.
  • formatter — string template. Use {b} for the slice name, {c} for the value, {d} for the percentage.
  • distance, align, vertical_align, clip.
chart:
  show_value_labels: true
  label:
    position: outside
    formatter: "{b}: {d}%"

Legend & tooltip

chart.legend controls the legend; chart.tooltip controls the hover tooltip. Both share the same shape as on bar — see that page for the full sub-block reference.

Pie-specific tip: for a donut variant with the legend on the right, set center: ["42%", "50%"] to nudge the donut left so the legend has more room.

format

  • format.y or format[<value_field_name>] — pattern for slice tooltip values and inside-slice labels.
  • format at the root — fallback.

Cross-filter behavior

  • Clicking a slice cross-filters the rest of the dashboard by the slice category (the mapping.x field).
  • The clicked field (the mapping.x field, e.g. status) must be declared as a parameter on a source signature in this viz's own model file, or the click is silently ignored.
  • Disable per viz with chart.cross_filter: false.

See Cross-filtering for the full mechanism.

Worked examples

Donut with outside labels and bottom legend — note min_angle keeping tiny slices visible and center nudging the donut up to make room for the legend:

id: ec_revenue_share_by_category_pie
title: Revenue share by category
query: "models/ec_revenue_share.malloy::revenue_share_by_category"
type: pie
mapping:
  x: category
  y: revenue
chart:
  variant: donut
  height: 480
  inner_radius: "52%"
  outer_radius: "80%"
  slice_border_radius: 4
  min_angle: 4
  show_value_labels: true
  label:
    position: outside
    formatter: "{b}: {d}%"
  center: ["50%", "48%"]
  legend:
    show: true
    position: bottom
    orient: horizontal
    item_gap: 14
  tooltip:
    trigger: item
format:
  revenue: "$#,##0a"
published: true

Solid pie with inside labels:

type: pie
mapping:
  x: category
  y: revenue
chart:
  show_value_labels: true
  label:
    position: inside
    color: "#fff"
    font_weight: bold
  legend:
    show: false
format:
  revenue: "$#,##0"

Rose layout (slice angle uniform, radius encodes value):

chart:
  variant: rose
  rose_type: area
  start_angle: 0
  show_value_labels: true

Design notes

  • Keep it to about six slices — sort and limit in the Malloy query, or aggregate small slices into an "Other" bucket.
  • chart.min_angle keeps near-zero slices visible; alternatively filter zeros out in the query.
  • On tight charts, place labels inside (chart.label.position: "inside") or rotate them.
  • For a donut with content in the center, set chart.label.position: "outside" so slice labels stay clear.
  • Colors follow query-result order from the platform palette — sort the query so the largest or most important slice takes the dominant color.