Visualize.Shape.Stack (Visualize v0.2.25)

Copy Markdown View Source

Stack generator for creating stacked bar and area charts.

Computes a baseline value for each datum, so you can stack layers of data on top of each other.

Examples

data = [
  %{month: "Jan", apples: 10, oranges: 20, bananas: 15},
  %{month: "Feb", apples: 15, oranges: 25, bananas: 10},
  %{month: "Mar", apples: 20, oranges: 15, bananas: 25}
]

stack = Visualize.Shape.Stack.new()
  |> Visualize.Shape.Stack.keys([:apples, :oranges, :bananas])

series = Visualize.Shape.Stack.generate(stack, data)
# Returns one series per key, in key order, each with :key, :index (its position
# in the stacking order) and :points. Points have :data, :y0 (baseline), :y1 (top).

Summary

Functions

Generates the stacked series data.

Sets the keys to stack.

Creates a new stack generator

Sets the stack offset.

Sets the stack order.

Sets the value accessor function.

Types

point()

@type point() :: %{
  key: any(),
  index: non_neg_integer(),
  data: any(),
  value: number(),
  y0: number(),
  y1: number()
}

series()

@type series() :: %{key: any(), index: non_neg_integer(), points: [point()]}

t()

@type t() :: %Visualize.Shape.Stack{
  keys: [any()],
  offset: :none | :expand | :diverging | :silhouette | :wiggle,
  order:
    :none | :ascending | :descending | :reverse | :insideout | {:keys, [any()]},
  value: (map(), any() -> number()) | nil
}

Functions

generate(stack, data)

@spec generate(t(), Visualize.Data.Table.source()) :: [series()]

Generates the stacked series data.

Returns one series per key, in key order, each a map with:

  • :key - The series key
  • :index - The series' position in the stacking order (0 is the bottom)
  • :points - One point per datum with :data, :value, :y0, :y1, :index

keys(stack, keys)

@spec keys(t(), [any()]) :: t()

Sets the keys to stack.

Keys determine the layers in the stack, typically field names.

new()

@spec new() :: t()

Creates a new stack generator

offset(stack, offset)

@spec offset(t(), atom()) :: t()

Sets the stack offset.

  • :none - Zero baseline (default)
  • :expand - Normalize to 0-1 (100% stacked)
  • :diverging - Positive values stack up from zero, negative values stack down from zero
  • :silhouette - Center the stack around zero
  • :wiggle - Minimize weighted wiggle (for streamgraphs)

order(stack, order)

@spec order(t(), atom() | {:keys, [any()]}) :: t()

Sets the stack order.

  • :none - Use key order (default)
  • :ascending - Smallest series on bottom
  • :descending - Largest series on bottom
  • :reverse - Reverse key order
  • :insideout - d3's stackOrderInsideOut: the earliest-peaking series in the middle, later ones outward on whichever side has the smaller sum (good for streamgraphs)
  • {:keys, list} - The listed keys bottom first, then the unlisted keys in key order; a listed key the stack does not have is ignored (spec/04 §8.4)

Every order but {:keys, list} is computed from the data generate/2 is given, so over a stream of data it can change between frames; {:keys, list} is fixed.

iex> alias Visualize.Shape.Stack
iex> Stack.new()
...> |> Stack.keys([:a, :b, :c])
...> |> Stack.order({:keys, [:c, :x, :a]})
...> |> Stack.generate([%{a: 1, b: 2, c: 3}])
...> |> Enum.map(&{&1.key, &1.index})
[a: 1, b: 2, c: 0]

value(stack, func)

@spec value(t(), (map(), any() -> number())) :: t()

Sets the value accessor function.

The function receives (datum, key) and returns a number.