Dojo charts that sing: box and whisker plots

A big part of my job at mSpoke is to understand our users, system performance, and our ability to deliver relevant content.  In order to facilitate this, we’ve been building a dashboard.  The dashboard is a group of web pages that enables us to easily monitor different aspects of our systems’ status.  I really can’t understate the importance of having the right tools available in order to do data analysis.  Our dashboard is an interactive, frequently updated suite of web pages and graphs that allow us to easily diagnose issues in our system, observe topical trends in live web content, and better understand which content receives our users’ attention.

We use a lot of Dojo at mSpoke, so it was an easy choice for us to use Dojo Charting to create the plots in our dashboard.  However, it doesn’t yet include some chart types we’d like.  So I built them.  This post covers our custom box and whisker plot.

A box and whisker plot elegantly displays distributional statistics about a set of data.  The box covers the middle 50% of the data, the line in the box shows the median, the whiskers cover the range of points that are not outliers, and the outliers are indicated using markers.

Dojo box and whisker chart

Dojo box and whisker chart

I’ve hosted an interactive version of the chart and the source code.  mSpoke is happy to share this code, and I would be happy to work with Dojo to include it in later releases.

Using the box and whisker plot

Creating a box and whisker plot is very similar to the creation of other Dojo charts.  In addition to including dojo.js, you’ll need to include BoxAndWhisker.js:

<script type="text/javascript" 
        src="mspoke/charting/plot2d/BoxAndWhisker.js"></script>

The javascript to create the plot is simple:

    var chart = new dojox.charting.Chart2D("chart");
    chart.addPlot("default", {type: "BoxAndWhisker", markers: true});

I’ve included two different ways to pass in the data for a series.  The first is to simply list all of the data points; BoxAndWhisker.js will compute the median, middle 50% of points, whiskers and outliers.

    var fill = new dojo.Color([0x00, 0x4f, 0x80, 0.7]);
    var stroke = {color:fill};

    // List all points approach
    chart.addSeries( "Mon",
      [4.4, 6.7, 5.7, 4.6, 4.1, 4.4, 4.3, 4, 3.5, 6.2, 6.5, 0.5],
      {stroke:stroke, fill:fill, center:1, width:0.2});

You must specify the center and width for the box to display properly.  The center indicates where the x-coordinate the box and whisker for the series will be placed and the width indicates the width along the x-axis of the box.  You can specify the range and labels of the axes using chart.addAxis.  View the source of the interactive version for an example.

The other approach is better suited for handling large data sets, when passing in all of the data would make the script run slowly.  In this case, you need to figure out the box and whisker coordinates yourself.

    // Pass in box and whisker coordinates and outliers
    chart.addSeries( "Tue",
      {lwhisker: 1.4, lbox: 2.9, median: 3.35, ubox: 5.1, uwhisker: 7.5,
       outliers: [0.2, 8.9]},
      {stroke:stroke, fill:fill , center:2, width:0.2});

lwhisker and uwhisker are the lower and upper points for the whiskers, lbox and ubox specify the range of the box, and median is the coordinate for the median line in the box.  You can specify the list of markers with the outliers parameter.  Complete source for constructing a box and whisker plot is available in the source of the interactive version.

Creating custom plot types

Building a custom Dojo plot isn’t extremely hard, but it takes some patience to get things just right.  The biggest quirk was that I had indicate in code that the BoxAndWhisker plot type is a part of dojox.charting.  I suspect I may be misunderstanding how to use the Dojo Toolkit correctly.  In order to make the chart visible to Dojo, BoxAndWhisker.js must use dojo.provide at the top of the file:

dojo.provide("dojox.charting.plot2d.BoxAndWhisker");

Following the example in other Dojo plots, I used dojo.declare to declare the plot constructur. As with the call to dojo.provide, I had to declare the plot to be a part of dojox.charting:

	dojo.declare("dojox.charting.plot2d.BoxAndWhisker",
                          dojox.charting.plot2d.Base, {

Otherwise, I was able to develop the chart by following the examples already provided in dojox.charting.plot2d.

Comments (8)

  1. Tom C wrote::

    Thanks Paul. This is very nice.

    I did find one problem with the code, however. It looks like the charts fail if you have orders-of-magnitude differences in the data values.

    For a simple example, consider this data:
    [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 10]

    This doesn’t work due to a bug in the code that sorts the data before doing the calculations.
    run.data.sort() does not do what you think it would. It sorts alphabetically (even for numbers!), so the above data end up looking like this:

    [1, 1, 10, 2, 2, 3, 3, 4, 4, 5, 5]

    (See: http://www.w3schools.com/jsref/jsref_sort.asp)

    I added a sort function locally, and it works like a charm.

    Great chart. I hope to see it added to the distro soon.

    Thursday, December 18, 2008 at 3:51 pm #
  2. pogil wrote::

    Tom, thanks for catching that bug. I’ve updated the code on my server and added a comment to the ticket in the Dojo Toolkit’s Trac system.

    Thursday, December 18, 2008 at 4:12 pm #
  3. Yuri N wrote::

    Great stuff. There is still a problem with ranges containing negative numbers. It seems to work when you just supply the arrays of values for the series. But if you send the objects with the properties lwisker, uwisker, median, etc, it does not display below the zero line.

    Sunday, March 15, 2009 at 11:50 am #
  4. Adrian N wrote::

    I find the example shown renders correctly in Firefox but not in IE which gives an illegal character Vector2D line 146 char 17

    Monday, March 16, 2009 at 1:59 am #
  5. Adrian N wrote::

    On further investigation, it appears that there are NaN results trying to be assigned to number vars. In Firefox these are ignored, and rendering continues. In IE they are flagged up as an error and rendering stops.

    Monday, March 23, 2009 at 4:38 am #
  6. pogil wrote::

    Adrian, thanks for digging into this further. I’ll try to take a look at this and Yuri’s problem later this week.

    Monday, March 23, 2009 at 4:45 am #
  7. Adrian N wrote::

    I have temporarily solved the problem by changing height from 0.5 to 1 It seems that IE does not like the decimal point. This needs to be changed for all heights. Then all works OK

    s.createRect… , height: 1

    Tuesday, March 24, 2009 at 4:34 am #
  8. pogil wrote::

    I’ve updated the code again to use Adrian’s fix of not using a height of 0.5.

    I also greatly improved the support for negative numbers to address Yuri’s problems and I think I am now correctly handing automatic axis range creation.

    Adrian and Yuri, I’d be interested in hearing whether your problems are now resolved.

    Tuesday, March 31, 2009 at 12:20 pm #