Mark types that render as annotations (rules, bands) rather than data layers.
Mark types that render as annotations (rules, bands) rather than data layers.
(check-type-override! option-key written ds col)Report a type override the column cannot carry out, naming the option and the column rather than dying in the scale several stages later.
:categorical is the override that does something: every value can
be the name of a group, so a column of numbers, dates or strings can
all be read as categories, and reading numbers that way -- hours,
years, identifiers -- is why the option exists.
The other two only ever confirm what the column already holds. There
is no number in "setosa" and no instant either, so :numerical on
a column of strings has nothing to read, and neither has :temporal
on a column of numbers. Both used to reach the cast, which reported
a String or a LocalDate and named neither the column nor the option
that sent it there.
Report a type override the column cannot carry out, naming the option and the column rather than dying in the scale several stages later. `:categorical` is the override that does something: every value can be the name of a group, so a column of numbers, dates or strings can all be read as categories, and reading numbers that way -- hours, years, identifiers -- is why the option exists. The other two only ever confirm what the column already holds. There is no number in "setosa" and no instant either, so `:numerical` on a column of strings has nothing to read, and neither has `:temporal` on a column of numbers. Both used to reach the cast, which reported a String or a LocalDate and named neither the column nor the option that sent it there.
(column-ref? v)True if v is a column reference (keyword or string). Both keyword and string column names are valid references.
True if v is a column reference (keyword or string). Both keyword and string column names are valid references.
(column-type ds col)Classify a dataset column as :categorical, :numerical, or :temporal.
The column name must literally match a column in the dataset.
Classify a dataset column as `:categorical`, `:numerical`, or `:temporal`. The column name must literally match a column in the dataset.
(composite-draft? x)True if x is a composite draft (a tree of sub-drafts with chrome-spec).
True if x is a composite draft (a tree of sub-drafts with chrome-spec).
(composite-plan? x)True if x is a composite plan (a tree of sub-plots with chrome).
True if x is a composite plan (a tree of sub-plots with chrome).
(cross xs ys)Cartesian product of two sequences.
Cartesian product of two sequences.
(draft? x)True if x is a draft (leaf or composite).
True if x is a draft (leaf or composite).
(epoch-ms->local-date-time ms)The inverse of temporal->epoch-ms, read at UTC -- the offset that
function converts with, so a value round-trips.
Needed wherever an epoch-ms number has to be shown as a date again:
an axis holds epoch-ms, and wadogo's :datetime scale formats
LocalDateTime and refuses a LocalDate.
The inverse of `temporal->epoch-ms`, read at UTC -- the offset that function converts with, so a value round-trips. Needed wherever an epoch-ms number has to be shown as a date again: an axis holds epoch-ms, and wadogo's `:datetime` scale formats `LocalDateTime` and refuses a `LocalDate`.
(format-local-date-time ldt)A LocalDateTime as a date string, dropping a midnight time of day so
a value that began life as a LocalDate reads back as one.
A `LocalDateTime` as a date string, dropping a midnight time of day so a value that began life as a `LocalDate` reads back as one.
(infer-column-types ds v)Detect x and y column types (:categorical, :numerical, :temporal).
Temporal columns are converted to epoch-ms numbers; their original
extents (as LocalDateTime) are preserved for wadogo :datetime ticks.
Returns a map with keys :ds, :x-type, :y-type, :x-temporal?,
:y-temporal?, :x-temporal-extent, :y-temporal-extent,
:x-resolved, :y-resolved.
Detect x and y column types (`:categorical`, `:numerical`, `:temporal`). Temporal columns are converted to epoch-ms numbers; their original extents (as `LocalDateTime`) are preserved for wadogo `:datetime` ticks. Returns a map with keys `:ds`, `:x-type`, `:y-type`, `:x-temporal?`, `:y-temporal?`, `:x-temporal-extent`, `:y-temporal-extent`, `:x-resolved`, `:y-resolved`.
(infer-grouping v color-type color-col)Build the grouping vector from explicit :group and categorical color column. Explicit groups are passed through; categorical color columns are appended. Returns a vector of column references (keywords or strings).
Build the grouping vector from explicit :group and categorical color column. Explicit groups are passed through; categorical color columns are appended. Returns a vector of column references (keywords or strings).
(infer-layer-type v x-type y-type x-temporal? y-temporal?)Choose mark and stat from column types when the user hasn't specified them. Rules:
x-type/y-type come from infer-column-types, which reports
temporal columns as :numerical (they're stored as epoch-ms);
x-temporal?/y-temporal? flag the original temporal classification.
When the user provides an explicit mark, stat defaults to :identity
unless they also provided an explicit stat.Choose mark and stat from column types when the user hasn't specified them. Rules: - x only, categorical → :rect + :count (bar chart) - x only, non-categorical → :bar + :bin (histogram) - temporal x + numerical y → :line + :identity (time-series line) - categorical x + numerical y → :boxplot + :boxplot (vertical) - numerical x + categorical y → :boxplot + :boxplot (horizontal) - otherwise → :point + :identity (scatter) `x-type`/`y-type` come from `infer-column-types`, which reports temporal columns as `:numerical` (they're stored as epoch-ms); `x-temporal?`/`y-temporal?` flag the original temporal classification. When the user provides an explicit mark, stat defaults to :identity unless they also provided an explicit stat.
(layer-type? x)True if x is a layer-type (mark + stat + position bundle).
True if x is a layer-type (mark + stat + position bundle).
(leaf-draft? x)True if x is a leaf draft (a vector of draft layers + pose-level opts).
True if x is a leaf draft (a vector of draft layers + pose-level opts).
(leaf-plan? x)True if x is a leaf plan (single-pose resolved geometry).
True if x is a leaf plan (single-pose resolved geometry).
(literal-position? v)True of a value that places a mark on its own, as {:x 6.5} does,
rather than naming a column to read one from. Numbers are the whole of
it today; a temporal value is coerced by the scale like any other, so
it counts too.
True of a value that places a mark on its own, as `{:x 6.5}` does,
rather than naming a column to read one from. Numbers are the whole of
it today; a temporal value is coerced by the scale like any other, so
it counts too.(plan-layer? x)True if x is a plan-layer (resolved geometry for one mark).
True if x is a plan-layer (resolved geometry for one mark).
(plan? x)True if x is a plan (leaf or composite).
True if x is a plan (leaf or composite).
The aesthetics whose literal value becomes a constant column before
anything else reads the mapping. Derived from
defaults/aesthetic-registry, which is where a new one is added.
Narrower than the glossary's positional aesthetics: the band bounds place a mark too, but their marks read the value straight from the mapping, so turning it into a column would take it from the only code that wants it.
The aesthetics whose literal value becomes a constant column before anything else reads the mapping. Derived from `defaults/aesthetic-registry`, which is where a new one is added. Narrower than the glossary's positional aesthetics: the band bounds place a mark too, but their marks read the value straight from the mapping, so turning it into a column would take it from the only code that wants it.
(resolve-aesthetics ds v)Classify each aesthetic channel (:color, :size, :alpha, :text) as either a column reference or a fixed value it is drawn as.
The data decides, uniformly: a value is a column reference when
the layer's data carries a column of that exact name, and is drawn
as it stands otherwise. That one rule replaces three that disagreed
-- :color looked the value up, :size and :alpha called anything
keyword-or-string a column without checking, and each was written
out separately here. impl.aesthetics/source is where it now lives,
and impl.pose/validate-columns reports a value that is neither a
column nor something the aesthetic can draw, so nothing arrives here
having failed both readings.
:text keeps the older test on purpose. Its drawn reading exists
only on a layer with no data -- impl.pose/resolve-positional-values
holds it -- and this function is only ever called with a dataset, so
asking the data here would turn a reported mistake into a layer that
draws no labels.
Returns a map with keys :color, :color-is-col?, :color-type, :fixed-color, :size, :size-is-col?, :fixed-size, :alpha, :alpha-is-col?, :fixed-alpha, :text-col.
Classify each aesthetic channel (:color, :size, :alpha, :text) as either a column reference or a fixed value it is drawn as. **The data decides**, uniformly: a value is a column reference when the layer's data carries a column of that exact name, and is drawn as it stands otherwise. That one rule replaces three that disagreed -- `:color` looked the value up, `:size` and `:alpha` called anything keyword-or-string a column without checking, and each was written out separately here. `impl.aesthetics/source` is where it now lives, and `impl.pose/validate-columns` reports a value that is neither a column nor something the aesthetic can draw, so nothing arrives here having failed both readings. `:text` keeps the older test on purpose. Its drawn reading exists only on a layer with no data -- `impl.pose/resolve-positional-values` holds it -- and this function is only ever called with a dataset, so asking the data here would turn a reported mistake into a layer that draws no labels. Returns a map with keys :color, :color-is-col?, :color-type, :fixed-color, :size, :size-is-col?, :fixed-size, :alpha, :alpha-is-col?, :fixed-alpha, :text-col.
(resolve-col-name _ds ref)Look up a column name in a dataset. Returns the name unchanged
whether or not the dataset contains it; the existence check is
informational. Matching is strict: :x does not match a column
literally named "x". The reference and the dataset column name
must be identical (same type, same characters).
Look up a column name in a dataset. Returns the name unchanged whether or not the dataset contains it; the existence check is informational. Matching is strict: `:x` does not match a column literally named `"x"`. The reference and the dataset column name must be identical (same type, same characters).
(resolve-draft-layer v)Resolve a single draft layer: infer column types, aesthetics, grouping, and layer type.
Delegates to infer-column-types, resolve-aesthetics, infer-grouping,
and infer-layer-type — each named for the inference step it performs.
Also normalizes user-facing shorthand options:
:bandwidth → :cfg {:<stat>-bandwidth ...} (routed per stat):tile with :fill → stat :identityResolve a single draft layer: infer column types, aesthetics, grouping, and layer type.
Delegates to `infer-column-types`, `resolve-aesthetics`, `infer-grouping`,
and `infer-layer-type` — each named for the inference step it performs.
Also normalizes user-facing shorthand options:
- `:bandwidth` → `:cfg {:<stat>-bandwidth ...}` (routed per stat)
- `:tile` with `:fill` → stat `:identity`(temporal->epoch-ms v)Convert a temporal value to epoch-milliseconds (double), through the
one reading temporal-readings gives it. Returns ##NaN for nil, and
coerces a number as it stands.
Every type goes by way of LocalDateTime at UTC rather than by a
shortcut of its own: two routes to one number are two things to keep
in step, and this list has already grown past the four it started
with.
Convert a temporal value to epoch-milliseconds (double), through the one reading `temporal-readings` gives it. Returns ##NaN for nil, and coerces a number as it stands. Every type goes by way of `LocalDateTime` at UTC rather than by a shortcut of its own: two routes to one number are two things to keep in step, and this list has already grown past the four it started with.
A temporal value as the LocalDateTime the tick generators read.
impl.temporal/->local-date-time.
A temporal value as the `LocalDateTime` the tick generators read. `impl.temporal/->local-date-time`.
True of a value a temporal axis reads as a date.
impl.temporal/temporal-value?, named here because this namespace is
where most callers already look.
True of a value a temporal axis reads as a date. `impl.temporal/temporal-value?`, named here because this namespace is where most callers already look.
What :x-type, :y-type and :color-type accept.
What `:x-type`, `:y-type` and `:color-type` accept.
(validate-continuous-aesthetics ds v)Throw a clear error when :size, :alpha or :fill names a
categorical column. Without it the column reaches the encoder and
dies casting a string to a number, naming neither the aesthetic nor
the column.
Throw a clear error when `:size`, `:alpha` or `:fill` names a categorical column. Without it the column reaches the encoder and dies casting a string to a number, naming neither the aesthetic nor the column.
(warn-unread-temporal! aesthetic ds col)Report a column of values that name a stretch of time rather than a moment, which an axis reads as categories.
A YearMonth is the one a reader meets: grouping by month is what
->year-month is for, and the column that comes back was drawn with
one tick per value -- a hundred and eighty of them over fifteen
years -- rather than on a calendar axis. Year and MonthDay are
the same shape.
Reported rather than converted. A YearMonth has no instant of its
own, so reading it as the first of the month is a decision, and one
the writer can make in a line. dev-notes/backlog.md holds the
question of whether Plotje should make it.
Report a column of values that name a stretch of time rather than a moment, which an axis reads as categories. A `YearMonth` is the one a reader meets: grouping by month is what `->year-month` is for, and the column that comes back was drawn with one tick per value -- a hundred and eighty of them over fifteen years -- rather than on a calendar axis. `Year` and `MonthDay` are the same shape. Reported rather than converted. A `YearMonth` has no instant of its own, so reading it as the first of the month is a decision, and one the writer can make in a line. `dev-notes/backlog.md` holds the question of whether Plotje should make it.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |