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.
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)
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.
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.
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.
I find the example shown renders correctly in Firefox but not in IE which gives an illegal character Vector2D line 146 char 17
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.
Adrian, thanks for digging into this further. I’ll try to take a look at this and Yuri’s problem later this week.
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
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.