Scales.DataRange (scales v0.1.0)

Copy Markdown View Source

The range of the data a scale has seen, trained a batch of values at a time: a continuous range, the lowest and highest finite number (train_continuous/2), or a discrete one, the levels seen, in order (train_discrete/3); with the key that orders values that have no levels of their own (level_key/1) and the key a value is matched by (key/1).

A range is :none until it has seen a value: a continuous one is then {low, high}, and a discrete one {levels, factor}, factor saying whether its first values were a factor's, whose levels keep the order they came in.

Summary

Functions

The key a value is matched by: a number as a float, so an integer and the float equal to it share one, and a negative zero is the zero it equals; any other value as it is.

The key that orders values with no levels of their own: nil after every value, and the values in Erlang's term order, so numbers come first, strings sort by their bytes and false comes before true. A factor's values are ordered by its levels instead.

The range, :none for none, widened to cover the finite numbers among values, R's train_continuous(): nil, :infinity, :neg_infinity and :nan widen nothing.

The discrete range {levels, factor}, {[], :none} before any, with values merged into its levels, R's train_discrete() with drop = TRUE; levels are the levels of the factor values are of, or :none for values with none of their own.

Functions

key(value)

@spec key(term()) :: term()

The key a value is matched by: a number as a float, so an integer and the float equal to it share one, and a negative zero is the zero it equals; any other value as it is.

Examples

iex> Scales.DataRange.key(4) === Scales.DataRange.key(4.0)
true

iex> Scales.DataRange.key(-0.0)
0.0

level_key(value)

@spec level_key(term()) :: {0, term()} | {1, nil}

The key that orders values with no levels of their own: nil after every value, and the values in Erlang's term order, so numbers come first, strings sort by their bytes and false comes before true. A factor's values are ordered by its levels instead.

Examples

iex> Enum.sort_by([nil, "b", 2, "a", true], &Scales.DataRange.level_key/1)
[2, true, "a", "b", nil]

train_continuous(range, values)

@spec train_continuous(:none | {number(), number()}, list()) ::
  :none | {number(), number()}

The range, :none for none, widened to cover the finite numbers among values, R's train_continuous(): nil, :infinity, :neg_infinity and :nan widen nothing.

Examples

iex> Scales.DataRange.train_continuous(:none, [nil, 3, :infinity, -2])
{-2, 3}

iex> Scales.DataRange.train_continuous({-2, 3}, [7])
{-2, 7}

train_discrete(range, values, levels)

@spec train_discrete({list(), :none | boolean()}, list(), list() | :none) ::
  {list(), :none | boolean()}

The discrete range {levels, factor}, {[], :none} before any, with values merged into its levels, R's train_discrete() with drop = TRUE; levels are the levels of the factor values are of, or :none for values with none of their own.

A factor's values bring the levels they hold, in the levels' order, the missing value after them; other values bring their distinct values sorted by level_key/1, nil last. Values are matched by key/1, so 4 and 4.0 are one level. A factor's levels lead the rest; and once a range's first values were a factor's, new values follow its levels, where otherwise every merge sorts them all again. No values merge nothing.

Examples

iex> Scales.DataRange.train_discrete({[], :none}, ["y", nil, "x"], :none)
{["x", "y", nil], false}

iex> Scales.DataRange.train_discrete({["x", "y", nil], false}, ["z", "x"], :none)
{["x", "y", "z", nil], false}

iex> Scales.DataRange.train_discrete({[], :none}, ["b", "a"], ["c", "b", "a"])
{["b", "a"], true}