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
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 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.