Skip to content

Axis Scales: Log, Pow, and Symlog

dbt Charts's default measure-axis scale is linear. When a metric spans several orders of magnitude (population counts, payload masses, request latencies) a linear scale compresses small values into an unreadable sliver near zero. Set scale.continuous.type on the measure axis to switch to a logarithmic, power, or symmetric-log scale instead.

type: log

axis_y.scale.continuous.type: log is first-class on line and area charts: dbt Charts validates the authoring surface (see below) and lets Vega-Lite own tick placement natively (log-decade ticks, computed from the data, never a fixed tick count).

A log scale is undefined at and below zero, so it is rejected whenever the y-axis data contains a value that is 0 or negative; see ERR-LOG-SCALE-REQUIRES-POSITIVE-DATA in the error reference. If your data can include 0 or negative values, use type: symlog instead; it behaves like a log scale away from zero but stays defined through it.

source: examples_db
queries:
  populations:
    type: values
    columns: [year, population]
    values:
      - ["1800", 990000000]
      - ["1900", 1650000000]
      - ["1950", 2536000000]
      - ["2000", 6127000000]
      - ["2025", 8200000000]
charts:
  world_population_log:
    query: populations
    type: line
    title: World Population (log scale)
    x: year
    y: population
    style:
      axis_y:
        scale:
          continuous:
            type: log
rows:
  - world_population_log
18001900195020002025100M200M300M400M500M1G2G3G4G5G10GWorld Population (Log Scale) Data as of 14:24 UTC on 6 Oct 2026 made withdbt Charts
▶

log.base sets the log base (default: Vega-Lite's 10):

style:
  axis_y:
    scale:
      continuous:
        type: log
        log:
          base: 2

type: pow / type: sqrt / type: symlog

These scale types reach Vega-Lite the same way type: log does, but without a first-class tick story; dbt Charts passes them straight through and does not validate or specialize tick placement for them the way it does for log. pow.exponent configures pow; symlog.constant configures symlog. Unlike log, their domains can include 0, so (verified) they don't hit the log-specific area-mark rendering issue below and need no explicit domain.

style:
  axis_y:
    scale:
      continuous:
        type: pow
        pow:
          exponent: 0.5

Tick cadence on a quantitative axis

Two fields under style.axis_x.ticks control how densely a quantitative axis is ticked. They answer different questions, and only one of them is exact.

ticks.count asks for a number of ticks. Vega-Lite treats it as a target and rounds to the nearest round-numbered ladder, so you get about this many:

style:
  axis_x:
    ticks:
      count: 4

ticks.step names the interval instead, and it is a floor Vega cannot go finer than: step: 1000 on a 0–4k axis ticks at exactly 0 / 1k / 2k / 3k / 4k:

style:
  axis_x:
    ticks:
      step: 1000

Reach for step over an explicit scale.values: [0, 1000, 2000, 3000, 4000] ladder. A values list freezes the axis against the data you had when you wrote it: the day a customer count passes 4,000 the ladder silently stops covering the data. step is a floor, not a list; Vega keeps choosing round numbers above it, and the axis keeps covering the range as it grows.

The two compose: count sets the target, step the floor.

On a temporal x-axis step means a multiple of a calendar grain and needs ticks.time_unit alongside it; see Time axes. On an ordinal or categorical x-axis the domain is discrete, so there is no tick interval to set, including a horizontal bar's axis_x, which is its category axis (the measure lives on axis_y). Authoring ticks.step on any of those raises rather than doing nothing.

Rules

A handful of authoring combinations are rejected at compile time rather than silently producing a misleading chart:

Rule Why
log.base requires type: log (same for pow.exponent/type: pow, symlog.constant/type: symlog) These params are meaningless without the matching scale type.
type: log + zero: true A log domain cannot include 0.
type: log + a domain bound at or below 0 A log scale is undefined at and below 0.
log.base at or below 0, or equal to 1 No logarithm exists in those bases.
type: log on a bar chart A bar's length encodes magnitude from zero; meaningless on a log scale. Use type: symlog on the bar chart, or switch to line or area for a log scale.
type: log + axis_y.ticks.count A target tick count is meaningless on a log axis; Vega-Lite computes log-decade ticks natively.
axis_x.ticks.step without ticks.time_unit on a non-quantitative x-axis A bare step is a numeric tick interval; only a quantitative scale has one. Add ticks.time_unit on a temporal axis; on a discrete axis, remove it.

See the YAML Schema Reference for the full scale style field list.