axiom

Guide · writing the question down

Dimensions, units and scope

Physics students learn early that you cannot add a length to a mass, and that checking dimensions catches most algebra errors before they cost anything. Statistical software almost universally does not do this — a dataframe column is a column of floats, and floats add.

Three things, kept separate on purpose

They all look like a units problem. Only one is.

Dimension

What kind of thing this is: currency, time, an outcome count, a number of entities. There is no conversion factor between different dimensions, at any exchange rate, ever.

A mismatch always raises. There is no flag to disable it, because the operation has no meaning to permit.

declared bases on this build: area, count, currency, entity, exposure_count, mass, outcome, pressure, time, volume

Unit

Which measure of that dimension: USD or EUR, days or weeks. Two units of the same dimension may be interconvertible — if somebody registered the factor.

A mismatch raises unless a conversion is registered, and when one is, the conversion writes a ledger line recording itself.

axiom ships no conversions; a domain declares the ones it needs

Scope

Which population, which window, which level of aggregation. The number is in the right units and means something else anyway.

Not an arithmetic problem at all. No factor fixes it; it is settled by a transfer plan and a named assumption, which is the subject of transportability.

handled by Estimand.transfer_to, not by units

Why the third one is the dangerous one

A dimension error stops the program. A unit error stops the program. A scope error produces a number in perfectly correct units that answers a question nobody asked — and it is the only one of the three that reaches a slide.

What it looks like

Three refusals from this build

Each of these is a real exception, raised while this page was being generated.

DimensionError An estimand's dimension is derived from its other facets and checked against the one declared, so a quantity cannot claim to be in a dimension its own definition does not produce:
estimand 'mismatched': declared dimension $ but a contrast of Y over N derives to Y
raises
DimensionError Converting USD to day:
cannot convert 'USD' [currency] to 'day' [time]: different dimensions
raises
UnitConversionError Converting day to month — the same dimension, but nobody said what a month is:
unit 'month' is not declared in the unit system
raises

The last one is the one that feels excessive and is not. Is a month thirty days, or a twelfth of a year, or the actual calendar month this row falls in? Those give different answers, the difference compounds over a long window, and the library has no business picking for you. Registering the factor takes one line and makes the choice visible to the next reader.

When it does convert

A conversion is a fact, and it still writes a line

Declared, then converted

2 weeks = 14 days

unit_conversion — “converted week to day by factor 7”

The ledger line carries no assumption: assumption is None, because seven days in a week is a fact somebody registered, not a claim that might fail. That distinction is load-bearing. A ledger where facts and assumptions look alike is a ledger nobody reads, and the whole point of the paper trail is that its unverified lines stand out.

Contrast that with a scope correction — “the twelve-week window caught 81% of the effect” — which does carry an assumption, names what would challenge it, and stays unverified until something checks it.

Why this earns its keep

The bug class it removes

01

Cost quietly added to effect

A cost-per-unit and an effect-per-unit are both floats, and a helper four layers down adds them. The result is a number in no dimension at all, and it propagates to a decision. With dimensions declared, this raises at the boundary.

02

Weekly and daily series joined on index

Two panels, both indexed 0…N, one weekly and one daily. Nothing complains; the effect comes out seven times too small. A declared time unit makes the join a conversion that either has a registered factor or refuses.

03

A standard deviation treated as a variance

The reason dimension exponents are fractions rather than integers: a standard deviation is the square root of a variance, so it is genuinely a different dimension, and mixing them is catchable rather than a matter of naming discipline.