Skip to content

Choosing the Right Chart

Before picking a visualization type, answer three questions about goal, content, and audience. Then pick the simplest chart that answers the question. Increase complexity only when the simpler form cannot convey the insight.

Start with the question, not the chart

Answer three questions before sketching a single axis:

  1. What is the goal? — Analysis (exploring data) or communication (presenting a finding)?
  2. What do you want to show? — A comparison, a trend, a proportion, a distribution, a relationship?
  3. Who is the audience? — Executives want high-level dashboards; analysts need granular detail; general audiences need familiar forms.

Write the chart's main statement first. It becomes a compass for every design decision that follows.

Decision framework by goal

GoalPrimary chart typesAvoid
Compare categoriesBar (vertical/horizontal), grouped bar, dot plot, bullet graphPie (if > 5 categories)
Show change over timeLine, area, column, slope chartPie/donut (no time axis)
Show proportions / part-to-wholeStacked bar (100%), donut, waffle, treemapLine charts
Show distributionHistogram, box plot, violin plot, density plotBar chart (categorical only)
Show relationships / correlationScatter plot, bubble chart, heatmapBar charts
Show rankingHorizontal bar (sorted), lollipop, slope chartPie charts
Show flow / movementSankey diagram, alluvial diagramStatic charts
Show hierarchyTreemap, sunburst, tree diagramFlat charts
Show geographic patternsChoropleth, symbol map, bubble mapNon-spatial charts
Show deviation from baselineDiverging bar, bullet graph, surplus/deficit lineStandard bar

Decision by data shape

Data shapeChart types
1 numeric variableHistogram, density plot, box plot
1 categorical variableBar chart, lollipop, pie/donut
Numeric + categorical (1 observation per group)Bar chart, lollipop, dot plot
Numeric + categorical (many observations per group)Box plot, violin plot, grouped bar
2 numeric variablesScatter plot, line chart (if ordered)
3+ numeric variablesBubble chart, parallel coordinates, heatmap
Multiple series over timeMulti-line, stacked area, small multiples
Hierarchical categoriesTreemap, sunburst, circle packing
Network / flowSankey, chord diagram, network diagram

Complexity escalation rule

TIP

Start with the simplest chart that answers the question. A bar chart that communicates clearly is better than a beautiful but confusing stream graph.

Increase complexity only when the simpler form cannot convey the insight. Stream graphs, sunbursts, radar charts, and chord diagrams are powerful — and dangerous. Each added dimension must earn its place.

When a table is better

If you have fewer than 5 numbers to present, a table often communicates more effectively than a chart. Tables allow precise value comparison; charts excel at showing patterns, trends, and relationships.

Example

To display "revenue this quarter vs. last quarter, and year-over-year growth" — that is three numbers. A small table beats any chart.

Worked example: two stories, two chart types

The same dataset rarely fits every story. The two samples below answer different questions about different shapes of data — and each picks the simplest form that works.

Trend over time → line chart:

bpc
chart line {
  title = "Bitcoin surged past $90,000 in 2024"
  description = "USD, year-end closing price"
  source = "CoinGecko"
  colors = "#f7931a"

  data {
    "2016" = 963
    "2020" = 28949
    "2021" = 46306
    "2022" = 16547
    "2024" = 93429
  }
}

From packages/lib/src/samples/bitcoin-price.bpc

Position over time is what the reader needs — a line uses x-position for the date and y-position for the value. A bar chart of the same data would force length comparisons that obscure the trend.

Part-to-whole → donut chart:

bpc
chart donut {
  title = "Chrome dominates with two-thirds of the desktop browser market"
  description = "Worldwide, January 2025"
  source = "StatCounter"
  displayAsPercentage = true

  data {
    "Chrome" = 65.7
    "Edge" = 13.1
    "Safari" = 8.9
    "Firefox" = 6.3
    "Opera" = 3.1
    "Others" = 2.9
  }
}

From packages/lib/src/samples/browser-market.bpc

Six categories summing to 100 % — the question is "how big a slice does Chrome own?" A donut answers it directly; a line chart cannot.

See also

Released under the MIT License. Built static-first — your data never leaves the page.