Spec files¶
The YAML a spec, a category registry or a registry of specs is written as, key by key. Specs as files shows the workflow; this is the format. A test holds every table here to the reader's own field registry, so a key the reader accepts cannot be missing from this page.
Every file starts with version: 4 -- polspec.FORMAT_VERSION, the format
version that wrote it. A
file from an older version is migrated as it is read; one from a newer
polspec is refused, naming the version it needs. A key the reader does not
know is an error naming the closest known key; strict=False downgrades it
to a warning. A key left out takes its default, and a writer leaves out
every key still at its default.
A spec file¶
Orders.to_yaml(path) and serialization.to_yaml(spec, path) write one;
FrameSpec.from_yaml(path) reads one.
| Key | Holds |
|---|---|
version |
The format version, 4 |
name |
The spec's name; foreign keys refer to a spec by it |
categories |
A category registry: a path to one (relative to the file), or one written inline |
columns |
Column name to column, in order |
unique_together |
A list of composite keys, each a list of column names |
foreign_keys |
A list of foreign keys |
checks |
A list of checks |
hierarchy |
A hierarchy |
order_by |
The columns the rows come sorted by, the first the major key |
descending |
Whether each order_by column runs high to low: true, or a list of one flag per column |
A column¶
Each key is the ColSpec field of the same name; see
ColSpec fields for what each means.
| Key | Written as |
|---|---|
dtype |
A dtype -- see Dtypes |
col_name |
A string |
nullable |
true or false |
bounds |
[min, max]; either end may be null. A Decimal's fractional ends are strings, such as '1.50', so they read back exactly; a time or a duration is tagged |
tags |
A string, or a list of them |
unique |
true or false |
null_probability |
A number from 0 to 1 |
nan_probability |
A number from 0 to 1 |
element_null_probability |
A number from 0 to 1 |
string_length |
[min, max] |
list_length |
[min, max] |
fields |
Field name to column, for a Struct -- or key and value, for a Map |
format |
A format's name, such as email |
extra_values |
A list of values beside the format's own, each on 1% of the rows; or a mapping of value to share |
pattern |
A regular expression |
seed_name |
A string |
distribution |
A distribution's name, such as normal |
distribution_params |
Parameter name to number |
choices |
A list of values; a time or a duration is tagged |
weights |
A list of numbers, one per choice |
rules |
A list of rules |
validators |
A list of checks, each over this column |
A rule¶
| Key | Written as |
|---|---|
when |
A predicate -- see Predicates |
choices |
A list of values |
weights |
A list of numbers, one per choice |
A check or validator¶
| Key | Written as |
|---|---|
expr |
A predicate |
name |
A string; defaults to the predicate written out |
description |
A string |
ignore_nulls |
true (the default: a null result passes) or false |
Only a check written with col() can be written to a file. One over a raw
pl.Expr is left out, with a warning naming it.
A foreign key¶
| Key | Written as |
|---|---|
columns |
A list of this spec's columns |
references |
The referenced spec's name, or self |
ref_columns |
A list of the referenced spec's columns, in the same order |
name |
A string; defaults to one derived from the columns and the target |
A hierarchy¶
| Key | Written as |
|---|---|
child |
The column holding a reference |
parent |
The column holding the reference it points at |
max_depth |
The deepest chain, in hops |
branching |
The mean children per reference |
roots |
How many ultimate parents |
A category registry¶
CatSpec.to_yaml(path) writes one; CatSpec.from_yaml(path) reads one,
and a spec file's categories: may name one.
| Key | Holds |
|---|---|
version |
The format version |
enums |
Name to a list of categories |
categoricals |
Name to a categorical: name, and optionally namespace, physical (UInt8, UInt16 or UInt32) and categories |
choices |
Name to a list of values, for a name that is neither |
A registry of specs¶
Registry.to_yaml(path) writes one; Registry.from_yaml(path) reads one.
| Key | Holds |
|---|---|
version |
The format version |
categories |
A category registry, inline or as a path |
specs |
Spec name to a spec, written as a spec file is but without version or name |
Dtypes¶
A dtype with no parameters is its name: Int8, Int16, Int32, Int64,
Int128, UInt8, UInt16, UInt32, UInt64, UInt128, Float16,
Float32, Float64, Boolean, String, Binary, Date, Time,
Datetime, Duration, Categorical and Null -- a column of nothing but
nulls, which is declared nullable: true. One with parameters is a mapping
of one key:
| Dtype | Written as |
|---|---|
Enum |
{Enum: [a, b, c]}, or {Enum: NAME} for a registry's |
Categorical |
{Categorical: {name: ..., namespace: ..., physical: ...}}, or {Categorical: NAME} for a registry's |
Datetime |
{Datetime: {time_unit: us, time_zone: UTC}} |
Duration |
{Duration: {time_unit: ms}} |
Decimal |
{Decimal: {precision: 10, scale: 2}} |
List |
{List: <dtype>} |
Array |
{Array: {inner: <dtype>, width: 3}} |
Struct |
{Struct: {field: <dtype>, ...}} |
Map |
{Map: {key: <dtype>, value: <dtype>}} -- Polars 2 only |
A bare name a category registry declares -- STATUS, or
$categories.STATUS -- is that registry's Enum or Categorical.
Predicates¶
A predicate is the data form of one written with col(): a mapping of one
operation to its operands, or a scalar for a literal. col("total") >=
col("subtotal") is written {ge: [{col: total}, {col: subtotal}]}.
| Operation | Operands |
|---|---|
col |
A column name |
lit |
A value; needed only for a list or mapping |
eq, ne, lt, le, gt, ge |
[left, right] |
add, sub, mul, div |
[left, right] |
and, or |
A list of two or more predicates |
not |
A predicate |
is_in |
[predicate, [values...]] |
is_null |
A predicate |
between |
[predicate, lower, upper] |
str_contains, str_starts_with, str_ends_with, str_matches |
[predicate, text]; str_matches is a regular expression, str_contains a literal substring |
str_len |
A predicate |
time, duration |
A literal time or duration, in its tagged form |
Times and durations¶
YAML has forms for numbers, text, dates, datetimes and bytes, and none for a time of day or a duration. Wherever a spec file holds one -- a bound, a choice, a rule's choice, a predicate's literal -- it is a mapping of one key saying which it is:
| Value | Written as |
|---|---|
datetime.time(12, 30) |
{time: "12:30:00"} -- the ISO form, microseconds included when there are any |
datetime.timedelta(days=1, hours=2) |
{duration: {days: 1, seconds: 7200, microseconds: 0}} -- timedelta's own fields; a field left out is 0 |
columns:
opens:
dtype: Time
bounds: [{time: "06:00:00"}, {time: "10:00:00"}]
checks:
- expr: {ne: [{col: opens}, {time: "08:00:00"}]}
name: not_eight
A file holding neither reads as before, so these are not a new format version: a file could not hold a time or a duration at all until 0.13.0.
Versions¶
| Version | Changed |
|---|---|
| 1 | The original format, with no version key: tags could be spelt category or categories, a rule's when was a one-column mapping such as {column: region, equals: UK}, and distribution parameters took any alias |
| 2 | version recorded; tags spelt tags; conditions and checks as predicates; distribution parameters canonical; foreign keys written with their target's name; checks and validators; registry files |
| 3 | hierarchy |
| 4 | nan_probability |
A key added without changing another's meaning -- format, pattern,
seed_name -- is not a new version: a file without it reads as before.
nan_probability is, because its absence makes a claim -- a float that does
not declare it holds no NaN -- that a reader too old to know the key would
not check: version 4 has that reader refuse the file by name instead of
reading it more loosely than it was written. Every file carries the current
version, so polspec 0.13 and earlier refuse every file 0.14.0 writes.