A graphical toolkit for visualization
Protovis
Overview
Examples
Documentation
Download
Index

Scales

Scales are functions that map from domain to range. Quantitative scales map from a continuous domain to a continuous range (e.g., real numbers to pixel positions): pv.Scale.linear, pv.Scale.root, pv.Scale.log. Quantile scales map from a continuous domain to a discrete range. Ordinal scales map from a discrete domain to a discrete range (e.g., names to colors): pv.Scale.ordinal, pv.Colors.

See also: pv.Scale API reference

Quantitative Scales

See also: pv.Scale.quantitative, linear, log, root API reference

Example with position, color and ticks

var data = pv.range(100).map(Math.random),
    w = 360,
    h = 360,
    x = pv.Scale.linear(0, 100).range(0, w),
    y = pv.Scale.linear(0, 1).range(0, h),
    c = pv.Scale.linear(data).range("#1f77b4", "#ff7f0e");

var vis = new pv.Panel()
    .width(w)
    .height(h)
    .margin(20)
    .strokeStyle("#ccc");

vis.add(pv.Rule)
    .data(x.ticks())
    .strokeStyle("#eee")
    .left(x)
  .anchor("bottom").add(pv.Label)
    .text(x.tickFormat);

vis.add(pv.Rule)
    .data(y.ticks())
    .strokeStyle("#eee")
    .bottom(y)
  .anchor("right").add(pv.Label)
    .text(y.tickFormat);

vis.add(pv.Dot)
    .data(data)
    .left(function() x(this.index))
    .bottom(y)
    .strokeStyle(c)
    .fillStyle(function(d) c(d).alpha(.2));

vis.render();

Example with angle

var data = [1, 1.2, 1.7, 1.5, .7];

var vis = new pv.Panel()
    .width(150)
    .height(150);

vis.add(pv.Wedge)
    .data(data)
    .left(75)
    .bottom(75)
    .innerRadius(50)
    .outerRadius(70)
    .angle(pv.Scale.linear(0, pv.sum(data)).range(0, 2 * Math.PI));

vis.render();

Example with diverging color

Replacing the definition of c above with a diverging scale:

var data = pv.range(100).map(Math.random),
    w = 360,
    h = 360,
    x = pv.Scale.linear(0, 100).range(0, w),
    y = pv.Scale.linear(0, 1).range(0, h),
    c = pv.Scale.linear(0, .5, 1).range("red", "yellow", "green");

var vis = new pv.Panel()
    .width(w)
    .height(h)
    .margin(20)
    .strokeStyle("#ccc");

vis.add(pv.Rule)
    .data(x.ticks())
    .strokeStyle("#eee")
    .left(x)
  .anchor("bottom").add(pv.Label)
    .text(x.tickFormat);

vis.add(pv.Rule)
    .data(y.ticks())
    .strokeStyle("#eee")
    .bottom(y)
  .anchor("right").add(pv.Label)
    .text(y.tickFormat);

vis.add(pv.Dot)
    .data(data)
    .left(function() x(this.index))
    .bottom(y)
    .strokeStyle(c)
    .fillStyle(function(d) c(d).alpha(.2));

vis.render();

Example with log transform

var data = pv.range(100).map(Math.random),
    w = 360,
    h  = 360,
    x = pv.Scale.linear(0, 100).range(0, w),
    y = pv.Scale.log(0.01, 1).range(0, h),
    c = pv.Scale.log(data).range("#1f77b4", "#ff7f0e");

var vis = new pv.Panel()
    .width(w)
    .height(h)
    .margin(20)
    .strokeStyle("#ccc");

vis.add(pv.Rule)
    .data(x.ticks())
    .strokeStyle("#eee")
    .left(x)
  .anchor("bottom").add(pv.Label)
    .text(x.tickFormat);

vis.add(pv.Rule)
    .data(y.ticks())
    .strokeStyle("#eee")
    .bottom(y)
  .anchor("right").add(pv.Label)
    .text(y.tickFormat);

vis.add(pv.Dot)
    .data(data)
    .left(function() x(this.index))
    .bottom(y)
    .strokeStyle(c)
    .fillStyle(function(d) c(d).alpha(.2));

vis.render();

Quantile Scales

Description forthcoming.
See also: pv.Scale.quantile API reference

Ordinal Scales

Example with position (bands) and color

var categories = "ABCDEFGHIJK".split(""),
    data = categories.map(function(c) [c, Math.random()]),
    w = 160,
    h = 360,
    x = pv.Scale.ordinal(categories).splitBanded(0, w, 4/5),
    y = pv.Scale.linear(0, 1).range(0, h),
    c = pv.Colors.category19(categories);

var vis = new pv.Panel()
    .width(w)
    .height(h)
    .margin(20)
    .strokeStyle("#ccc");

vis.add(pv.Bar)
    .data(data)
    .left(function(d) x(d[0]))
    .width(x.range().band)
    .bottom(0)
    .height(function(d) y(d[1]))
    .fillStyle(function(d) c(d[0]))
  .anchor("bottom").add(pv.Label)
    .textBaseline("top")
    .text(function(d) d[0]);

vis.add(pv.Rule)
    .data(y.ticks())
    .strokeStyle("rgba(255, 255, 255, .5)")
    .bottom(y)
  .anchor("right").add(pv.Label)
    .text(y.tickFormat);

vis.render();

Example with position (points)

var categories = "ABCDEF".split(""),
    data = pv.range(100).map(function(d, i) [Math.random(), categories[i % 6]]),
    w = 160,
    h = 360,
    x = pv.Scale.ordinal(categories).split(0, w),
    y = pv.Scale.linear(0, 1).range(0, h),
    c = pv.Scale.linear(0, .5, 1).range("red", "yellow", "green");

var vis = new pv.Panel()
    .width(w)
    .height(h)
    .margin(20)
    .strokeStyle("#ccc");

vis.add(pv.Rule)
    .data(categories)
    .strokeStyle("#eee")
    .left(x)
  .anchor("bottom").add(pv.Label);

vis.add(pv.Rule)
    .data(y.ticks())
    .strokeStyle("#eee")
    .bottom(y)
  .anchor("right").add(pv.Label);

vis.add(pv.Dot)
    .data(data)
    .left(function(d) x(d[1]))
    .bottom(function(d) y(d[0]))
    .strokeStyle(function(d) c(d[0]))
    .fillStyle(function(d) c(d[0]).alpha(.2));

vis.render();

Other Features

The by method is a shorthand way of binding an accessor function with the scale. This method is provided for convenience, such that scales can be succinctly defined inline. For example, given an array of data elements that have a score attribute with the domain [0, 1], the height property could be specified as:

    .height(pv.Scale.linear(0, 1).range(0, 480).by(function(d) d.score))

This is shorthand for:

var y = pv.Scale.linear(0, 1).range(0, 480);

...

    .height(function(d) y(d.score))

This method should be used judiciously; it is typically more clear to invoke the scale directly, passing in the value to be scaled. Most commonly, the by method is used in conjunction with categorical color scales. There are also several pre-defined accessor functions for convenience:

For example, the default fill color for bars is

pv.Colors.category20().by(pv.parent)

which causes bars to be filled with a unique color according to the parent panel index. Since the parent panel data is typically a two-dimensional array of each series of data, this causes bars of the same series to share a color by default.

Copyright 2010 Stanford Visualization Group