Visualize.Scale.Threshold (Visualize v0.2.35)

Copy Markdown View Source

Threshold scale for mapping continuous values to discrete outputs.

Unlike quantize scales which divide the domain into uniform segments, threshold scales use explicit breakpoints. This is useful when you have specific cutoff values (e.g., grades, risk levels, categories with defined boundaries).

Examples

# Map test scores to letter grades
scale = Visualize.Scale.Threshold.new()
  |> Visualize.Scale.Threshold.domain([60, 70, 80, 90])
  |> Visualize.Scale.Threshold.range(["F", "D", "C", "B", "A"])

Visualize.Scale.Threshold.apply(scale, 55)   # => "F"
Visualize.Scale.Threshold.apply(scale, 65)   # => "D"
Visualize.Scale.Threshold.apply(scale, 75)   # => "C"
Visualize.Scale.Threshold.apply(scale, 85)   # => "B"
Visualize.Scale.Threshold.apply(scale, 95)   # => "A"

# Map values to colors for a choropleth
scale = Visualize.Scale.Threshold.new()
  |> Visualize.Scale.Threshold.domain([100, 500, 1000, 5000])
  |> Visualize.Scale.Threshold.range(["#f7fbff", "#c6dbef", "#6baed6", "#2171b5", "#084594"])

# Get the extent that maps to a specific range value
Visualize.Scale.Threshold.invert_extent(scale, "#6baed6")  # => {500, 1000}

Note

The range must have exactly one more element than the domain. For n thresholds, you need n+1 output values.

Summary

Functions

Maps a continuous value to a discrete range value.

Returns 0: a threshold scale has no bandwidth

Identity: a threshold scale always maps into its range

Returns a copy of the scale with a new domain inferred from data.

Sets the domain (threshold values).

Returns nil: a threshold scale maps many values to one bucket

Returns the extent of domain values that map to a given range value.

Creates a new threshold scale

Identity

Identity: a threshold scale has no padding

Sets the range (output values).

Alias of apply/2, kept for one release (spec/03 §1.3)

Returns the thresholds (same as domain).

Returns the thresholds (the domain); the count is ignored

Types

t()

@type t() :: %Visualize.Scale.Threshold{domain: [number()], range: [any()]}

Functions

apply(threshold, value)

@spec apply(t(), number()) :: any()

Maps a continuous value to a discrete range value.

Uses binary search to efficiently find the appropriate bucket.

bandwidth(threshold)

@spec bandwidth(t()) :: 0

Returns 0: a threshold scale has no bandwidth

clamp(scale, clamp?)

@spec clamp(t(), boolean()) :: t()

Identity: a threshold scale always maps into its range

copy_with_domain(scale, data, n)

@spec copy_with_domain(t(), [number()], non_neg_integer()) :: t()

Returns a copy of the scale with a new domain inferred from data.

Creates thresholds that divide the data into n+1 approximately equal groups (similar to quantiles but with fixed bucket count).

domain(scale, thresholds)

@spec domain(t(), [number()]) :: t()

Sets the domain (threshold values).

The domain should be a sorted list of threshold values. Values below the first threshold map to the first range value.

invert(threshold, value)

@spec invert(t(), any()) :: nil

Returns nil: a threshold scale maps many values to one bucket

invert_extent(threshold, value)

@spec invert_extent(t(), any()) ::
  {number() | :neg_infinity, number() | :infinity} | nil

Returns the extent of domain values that map to a given range value.

Returns {lower_bound, upper_bound} where:

  • lower_bound is the threshold at or below which values map to this range value
  • upper_bound is the threshold above which values no longer map to this range value

For the first bucket, lower_bound is :neg_infinity. For the last bucket, upper_bound is :infinity.

new()

@spec new() :: t()

Creates a new threshold scale

nice(scale)

@spec nice(t()) :: t()

Identity

padding(scale, padding)

@spec padding(t(), number()) :: t()

Identity: a threshold scale has no padding

range(scale, values)

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

Sets the range (output values).

The range must have exactly one more element than the domain.

scale(scale, value)

@spec scale(t(), number()) :: any()

Alias of apply/2, kept for one release (spec/03 §1.3)

thresholds(threshold)

@spec thresholds(t()) :: [number()]

Returns the thresholds (same as domain).

ticks(scale, count)

@spec ticks(t(), integer()) :: [number()]

Returns the thresholds (the domain); the count is ignored