Box Plot

A box plot is a standardized way of displaying the distribution of data based on the five number summary: minimum, first quartile, median, third quartile, and maximum. This example shows a box plot showing growth of sepals, built in HTML / JavaScript with source code that you can edit to see changes in visualization.

main
run-button
run-button
reset-button
// Data is fetched from https://www.charts.com/static/iris-cleared/data.json and assigned to the variable data.
// Schema is fetched from https://www.charts.com/static/iris-cleared/schema.json and assigned to the variable schema.
// Layers are fetched from https://www.charts.com/static/iris-cleared/layers.json and assigned to the variable layers.
// An element with id `chart-container` is available in the DOM to house the visualization
// Retrieves the DataModel from muze namespace. Muze recognizes DataModel as a first class source of data.

let DataModel = muze.DataModel;
let rootData = new DataModel(data, schema);
// Registry for user defined layers
let layerFactory = muze.layerFactory;
// Compose share operator for plotting multiple variable in one Y-axis
let share = muze.Operators.share;

// Create a global environment to share common configs across charts 
let env = muze();
// Set height, width and data to env, so that every instance of canvas which gets created from the environment
// receives this
env.width(600)
    .height(400)
    .data(rootData);
    
let canvas = env.canvas();

// Use the custom layer definition to register a new layer and name it boxMark
layerFactory.composeLayers('boxMark', layers);

// Create a combined field which gets plotted in the Y-axis. Value of all those variables will be passed
// to layers
let columns = [sharedField = share('minValue', 'meanValue', 'maxValue', 'quarter', 'thirdQuarter')];
let rows = ['organ'];

canvas
    .rows(columns)
    .columns(rows)
    .color('organ')
    .config({
        axes: {
            y: {
                showAxisName: true,
                name: 'Measure'
            }
        }
    })
    .layers([{
        mark: 'boxMark',
        encoding: { // Map the encoding with variables. These custom encodings are used in the composite layers.
            minValue: 'minValue',
            meanValue: 'meanValue',
            x: 'organ',
            maxValue: 'maxValue',
            quarter: 'quarter',
            thirdQuarter: 'thirdQuarter'
        }
    }])
    .title('Boxplot using layer composition')
    .subtitle('Iris sepalLength distrubution')
    .mount(document.getElementById('chart-container'));

What is Box Plot?

A box plot is a standardized way of displaying the distribution of data based on the five number summary: minimum, first quartile, median, third quartile, and maximum. It simply represents statistical data on a plot in which a rectangle is drawn to represent the second and third quartiles, usually with a vertical line inside to indicate the median value. The lower and upper quartiles are shown as horizontal lines either side of the rectangle.

Data

The above visualization is created from this data, this schema.

Layers definition

Muze does not have a high level mark (plot type) called BoxPlot. However, Muze exposes API using which you can compose layers which represent highlevel mark like BoxPlot using low level marks like bar, line, etc. Read more about composing layers here. This layer definition config is used to create the box plot.

Steps to create Box Plot

Following are the steps we need to do to create the above visualization

  • Create an instance of DataModel from data and schema
  • Provide rows and columns to the canvas for axes
  • Provide color encoding to the canvas
  • Add layers to the canvas for composing layers in the visualization
  • Add title and subtitle to canvas
  • Finally, mount the chart to the DOM.

Create an instance of DataModel from data and schema

The execution environment has stored the data and schema in data and schema variable. DataModel is retrieved from muze namespace. Here we write the following code to create an instance of DataModel from JSON data

const DataModel = muze.DataModel;
const rootData = new DataModel(data, schema); 

Read more about schema and DataModel here. Head here if you want to know Muze takes instance of DataModel to show a chart.

Assign fields to encoding channel

Based on what we what we want to see in X and Y-axis, we have to call rows and columns with the correct fields to achieve the above chart. Here is an intuitive guide on how rows and columns determine the layouting.

If you look at the layer definition file carefully, the boxMark expects multiple variable to draw the mark completely. Hence, Our Y-axis is created from multiple variables (fields) of same unit.

Let's deviate from this example to see why a shared variable is needed to plot multiple variables in one axis. We assume, we have age field which records age of every user who use a product. We want to see max age and min age of users over the years as a range plot like the following chart.

rangePlot Now both fields (max age and min age) is derived from age, hence min and max age is of type age only. There is no harm to put those two fields in same axis.

But we can't do it in Muze by passing those two fields in rows and columns as planer encoding methods do not support creating single instance of axis from two different fields until explicitly mentioned. share operator takes multiple similar fields and create a SharedField which can be used to create an axis.

Coming to our BoxPlot example, the Y-Axis is created using a SharedField derived by applying share operator on minValue, meanValue, maxValue, quarter, thirdQuarter. Organ is plotted on X-Axis.

let columns = [sharedField = share('minValue', 'meanValue', 'maxValue', 'quarter', 'thirdQuarter')];
let rows = ['organ'];

canvas
    .rows(columns)
    .columns(rows)
    .color('organ')

All we have done is create a Y-Axis from multiple fields and pass those individual fields to boxMark.

Format axis labels

Since we have combined quite a few fields here to make up the Y-axis, hence we remove the label of the Y-axis as:

.config({
  axes: {
      y: {
        showAxisName: false
      }
  }
})

Add layers to visualization

The visuals of BoxPlot is achieved by composing {atomic layers](/muze/docs/introduction-to-layers) which Muze provides out of the box. This layer definition config is used to generate the desired visual.

Once the definition is created, we can register the definition in Muze's layer registry and use it as simple marks.

let layerFactory = muze.layerFactory;
layerFactory.composeLayers('boxMark', layers);

Read more about layers basics and composition of layers .

We use the custom layer in our code as follows:

.layers([{
    mark: 'boxMark',
    encoding: { // Map the encoding with variables. These custom encodings are used in the composite layers.
      minValue: 'minValue',
      meanValue: 'meanValue',
      x: 'organ',
      maxValue: 'maxValue',
      quarter: 'quarter',
      thirdQuarter: 'thirdQuarter'
    }
}])

Add title and subtitle to canvas

Add a title and subtitle to the canvas

canvas
   .title('Composing Boxplot', { position: 'bottom', align: 'right' })
   .subtitle('Iris sepalLength distrubution', { position: 'bottom', align: 'right' })

Read more about title and subtitle here.

Mount the chart to the DOM

Finally attach the canvas instance to DOM which houses the visualization

canvas.mount('#chart-container');

An element with id chart-container is available in the DOM to house the visualization.