Skip to main content
In the Graphy SDK, your data and your spec are separate. Data is a plain table you pass to 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:
The 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 to mapping (or the createSpec shorthand) are column keys:
Because the binding is by key, the 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:
  1. The year pass. Across the first 5 non-empty rows, the first column whose non-empty cells are at least two values and all fall between 1900 and 2199 is read as a temporal year column. This is what keeps a 2021, 2022, 2023 column off a numeric axis.
  2. The first non-empty cell. Every other column takes its format from its first non-empty cell alone, tried in this order: number → date → weekly date range → percentage → currency → text.
Then every cell in the column is parsed under that one format. A cell that doesn’t fit becomes null — silently, with no warning. Order in the data therefore matters:
If a column looks empty on the chart, check its first non-empty cell first.

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:
Short month names (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.
A bare numeric cell inside a percentage column passes through unscaled, so a 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: $, , £, ¥, , , , , , , ฿, , , , kr, Fr, R, P, R$, Rp, RM, د.إ, , Ch$, NT$, HK$, S$, A$, C$, NZ$, MX$.
Symbols can appear as prefix or suffix, and negative values are supported (-$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 datetime scale.
The visual aesthetics read the same formats differently. On 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 is null, 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.
How a geom treats the resulting gaps is geom-specific — for lines, the 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.
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.