GraphProvider as the data prop; the spec references that table’s columns by key through its mapping. Keeping them apart means the same spec can be re-used across datasets, and the same data can be drawn several ways.
Basic structure
Data is a table with explicitly defined columns and rows:columns array defines the shape; rows holds the values.
Referencing columns from a spec
A spec never contains data — it names the columns it needs through its mapping. The variable strings you pass tomapping (or the createSpec shorthand) are column keys:
label on a column is purely presentational — it’s what shows in axes, legends and tooltips. If you omit it, the key is used.
Row keys must exactly match a column
key. Values under keys with no matching
column definition are ignored.Value format detection
Every column gets one value format, which drives how a scale interprets it and how the renderer formats it. Inference runs per column, in two passes:- The year pass. Across the first 5 non-empty rows, the first undeclared column whose non-empty cells are at least two whole numbers between 1800 and 2199 is read as a temporal
yearcolumn. This is what keeps a2021, 2022, 2023column off a numeric axis. If any column declaresvalueFormat: { type: 'year' }, this pass is skipped. - The first non-empty cell. Every other undeclared column takes its format from its first non-empty cell alone, tried in this order: number → date → weekly date range → percentage → currency → text.
null — silently, with no warning. Order in the data therefore matters:
Declaring a format
The same cell can mean two things:2010 is a headcount or a year, '1' a category or a number. When you know, set valueFormat on the column. A declared column skips inference and is parsed and formatted under that format:
dateFormat its cells use, such as { type: 'date', dateFormat: 'dd-MM-yyyy' }. A cell that does not fit becomes null, as under inference.
Declare a numeric format for every count column whose values could look like years. Declaring a column named year as integer keeps that column numeric, but the year pass still checks undeclared siblings. For example, an undeclared population column containing 1950, 2000 would become dates. Declare both to keep both numeric:
type: 'year' stops the year pass for the whole table; an integer declaration does not.
Numbers
Numbers and numeric strings are detected as quantitative values. Thousands separators, decimals and magnitude suffixes are supported:Dates
Date-like strings are parsed automatically across a wide range of formats — ISO dates, named months and locale-specific orderings:Jan, Feb) are recognised alongside full names. Set data._metadata.parsingLocale to control whether ambiguous dates like 01/02/2024 are read day-first (en-GB, pt-PT, ar) or month-first (en-US).
Weekly date ranges are also detected — values like 1 Feb – 7 Feb or 1 Feb 2024 – 7 Feb 2024 representing 7-day spans.
Dates without a year
A format that carries no year —month (Jan), day_month (14 Jan) or a weekly range without one — gets a synthetic year assigned by walking the column in row order, one sequence per color group. Each time the sequence wraps past December, the year advances. That’s why Jan … Dec, Jan, Feb reads as 14 consecutive months rather than folding back onto itself — and why reordering the rows moves the axis.
Percentages
Values with a% suffix are detected as percentages, and stored as fractions: '64.5%' becomes 0.645. The renderer multiplies by 100 again when it formats, so the axis reads back as you wrote it.
12 sitting among '64.5%' values renders as 1200%. Write '12%' to keep the column consistent.
Currencies
Currency-formatted strings are parsed with automatic symbol recognition. Supported symbols:$, €, £, ¥, ₹, ₱, ₩, ₪, ₫, ₽, ฿, ₦, ₺, zł, kr, Fr, R, P, R$, Rp, RM, د.إ, ﷼, Ch$, NT$, HK$, S$, A$, C$, NZ$, MX$.
-$100, $-100).
Text
Any value that doesn’t match the above is treated as text (categorical data).How formats reach scales
The inferred format feeds the scale you declare for each aesthetic. Calling a position scale bare (scale.x()) lets the engine choose a scale type from the column’s format. For the position aesthetics — x, y, ySecondary:
- A text column → a discrete (band) scale.
- A numeric, percentage or currency column → a continuous scale.
- A date column → a
datetimescale.
color, size, alpha and strokeWidth, a date column infers continuous — timestamps become plain numbers, since a colour ramp needs no date-aware ticks. On lineType, every format infers discrete. And an aesthetic bound to a constant ({ value: 5 }), left unmapped, or pointing at a column that isn’t in the data falls back to continuous.
You can always override the inference with an explicit method — scale.x.continuous(), scale.x.discrete(), scale.x.datetime() — when you want to force a particular treatment. See the line chart guide for worked examples.
Empty and missing values
A cell counts as empty when it isnull, undefined, an empty or whitespace-only string, or '-'. Empties become null in the parsed column, and two rules follow from that:
- A row whose every cell is empty is dropped.
- A column with no non-empty cell at all is dropped, so nothing can map to it.
missingValues param chooses whether to break the path, bridge it, or treat the gap as zero.
Schema
Column[]
required
Array of column definitions. Each column defines the structure and metadata
for a data field.
string
required
Unique, stable identifier for the column. Must match the keys used in
rows
objects, and is what a spec’s mapping references.string
Human-readable label shown in the UI (axis labels, legends, tooltips).
Defaults to the
key if not provided.ExplicitValueFormat
How to read the column’s cells when you know better than inference, for
example
{ type: 'integer' }, { type: 'text' } or
{ type: 'currency', iso: 'usd' }. A declared column skips inference; see
Declaring a format.Row[]
required
Array of data rows. Each row is an object with keys matching the column keys.
Values can be a
string, number, Date or null.object
Host state carried alongside the table. The engine reads
parsingLocale; the
remaining keys are set by the Graphy editor and are not part of the SDK’s
authoring surface.There are two
parsingLocale settings, and they do different jobs.
data._metadata.parsingLocale (default 'en-GB') decides how input cells are
parsed. config({ parsingLocale }) (default 'en-US') decides how values are
formatted for display, and is what formattingLocale on GraphProvider
overrides. Setting the config one does not change how a date string is read.
