Scales (scales v0.1.0)

Copy Markdown View Source

R's scales package for Elixir: the pieces a chart's scales are built from, as plain functions of values, for any charting tool. Each gives the answer R's scales 1.4.0 gives, to the last digit; where one departs from R, its documentation says how and why.

The families

Each module holds one of R's families, and each function is R's name less the family's prefix, its documentation naming R's: R's breaks_extended() is Scales.Breaks.extended/2.

ModuleWhat it holdsR's family
Scales.Breakswhere an axis's breaks gobreaks_*
Scales.MinorBreaksminor breaks between themregular_minor_breaks(), minor_breaks_*
Scales.Labelslabels for breakslabel_*, cut_*
Scales.Transformtransformations, with their breaks and labelstransform_*
Scales.Palettepalettes, from a place or a count to an aesthetic's valuepal_*, palette_*, as_*_pal()
Scales.Boundsrescaling, zero width, widening, values outside a rangerescale*, oob_*, zero_range(), expand_range()
Scales.DataRangethe range of the data a scale has seentrain_*
Scales.ColorOperationscolours as written and as R's palettes make themcol_*

Conventions

  • A range is {low, high}.
  • A double is held as R holds one (double/0): nil is R's NA, a missing value, :nan R's NaN, and :infinity and :neg_infinity R's infinities.
  • A colour is uppercase #RRGGBB, or #RRGGBBAA with an alpha of its own; :none is no colour, R's NA.
  • A function takes a list where R takes a vector, and its options as a keyword list of R's arguments, spelled out, checked as it is called: a bad one raises.
  • A colour operation takes one colour, where R takes a vector of them: a list of colours is mapped through it.
  • Elixir's words stand where R's differ: :time is a time of day (R's hms), {:datetime, ...} a date-time (R's POSIXct), and grey is gray.
  • A step on a calendar or a clock is written as Date.shift/2 takes one, [month: 1], where R writes "1 month".

An example

The steps a charting tool takes for a continuous colour scale: train a range on the data, find its breaks, some of which may fall outside it, label them, and map each value through a palette by its place in the range.

iex> values = [12.0, 31.5, 18.25, nil]
iex> range = Scales.DataRange.train_continuous(:none, values)
{12.0, 31.5}
iex> breaks = Scales.Breaks.extended(range)
[10.0, 15.0, 20.0, 25.0, 30.0]
iex> Scales.Labels.comma(breaks, suffix: " km")
["10 km", "15 km", "20 km", "25 km", "30 km"]
iex> places = Scales.Bounds.rescale(values, range, {0, 1})
[0.0, 1.0, 0.32051282051282054, nil]
iex> Scales.Palette.continuous({:gradient, ["#132B43", "#56B1F7"]}, places)
["#132B43", "#56B1F7", "#275278", nil]

Summary

Types

A double as R holds one: a number; :infinity or :neg_infinity; :nan, R's NaN, not a number; or nil, R's NA, a missing value.

Types

double()

@type double() :: number() | :infinity | :neg_infinity | :nan | nil

A double as R holds one: a number; :infinity or :neg_infinity; :nan, R's NaN, not a number; or nil, R's NA, a missing value.