Visualizing Data – jqPlot & gRaphaël

Learn how to create your very own rich and intuitive JavaScript data visualizations using jqPlotGo in-depth with jqPlot and learn how to integrate it with your company’s data analysis with my new book, Learning jqPlot.
Amazon.com (affiliate link)
Packt Publishing (available ebook & paperback combo)

My supervisor mentioned to me about a month ago that the doctors want a dashboard on our website to track various data points.

  • How many patients were seen in a week.
  • How many patients did each doctor see.
  • What were type of visit were the patients coming in for.
  • The wish list could go on…

Things were slow for a couple of days so I dove back into my research into Javascript graphing plugins.  I came across jqPlot and gRaphaël as two good candidates.  I liked the wide variety of graphing possibilities with jqPlot.  gRaphaël looked really pretty.  But all of this was judging the book by its cover.

I had begun playing with some of the examples on the jqPlot site but went ahead and started writing the queries and JSON calls to get all my data.  After all that was done, I needed to write the code to create the graphs and charts.

    $(function() {
                    /* All you need is the first two values, but I need to pass the other data to make each point interactive.
                       You'll notice that I pass the Y value twice.  That's because jqPlot uses the last value for the point label. */
            plot2 = $.jqplot('linegraph', [[[1,0,11,null,null,2008,0], ... [22,291,11,1211781600,1212300000,2008,291]], [[1,227,17,1263189600,1263708000,2010,227], ... [53,0,17,null,null,2010,0]]], {
                legend:{show:true, location:'se', xoffset:-255},
                title:'Total Patients by Week of Year',
                seriesDefaults:{
                    showMarker:true,
                    rendererOptions:{barPadding: 8, barMargin: 20},
                    showMarker:false,
                    isDragable: false,
                    lineWidth:2
                },
                series:[
                    {label:'Joshua Family Medical Care - 2008', markerOptions:{style:'dimaond'} }, {label:'Joshua Family Medical Care - 2009', markerOptions:{style:'dimaond'} }, {label:'Joshua Family Medical Care - 2010', markerOptions:{style:'dimaond'} }, {label:'Crowley Clinic - Total Care - 2008', markerOptions:{style:'x'} }, {label:'Crowley Clinic - Total Care - 2009', markerOptions:{style:'x'} }, {label:'Crowley Clinic - Total Care - 2010', markerOptions:{style:'x'} }                ],
                axesDefaults: {
                    tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
                    tickOptions: {
                        angle: -60,
                        fontSize: '10pt'
                    }
                },
                axes:{
                    xaxis:{
                        showLabel: true,
                         ticks:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54],
                         tickOptions:{formatString:'%d'},
                         label:'Week of the Year'

                    },
                    yaxis:{
                        min:0,
                        tickOptions:{formatString:'%d'},
                        label:'Number of Patients'
                    }
                },
                cursor: {
                    zoom:true,
                    showCursorLegend:false,
                    showTooltip: false
                }
            });

            $.jqplot.eventListenerHooks.push(['jqplotClick', myClickHandler]);

            function myClickHandler(ev, gridpos, datapos, neighbor, plot) {

                var pieJson;
                var pieLabels;
                var pieValues;
                var pieTitle;

                $.getJSON("charts_json_weekly.php?start="+neighbor.data[3]+"&end="+neighbor.data[4]+"&facilityid="+neighbor.data[2],
                    function(data){
                        $.each(data, function(i,item){                                                

                            pieTitle = item['Clinic']+'\nWeek of '+item.date+'\nTotal Visits: '+neighbor.data[1];
                            pieLabels = ['OV - '+item['OV'], 'OV-WI - '+item['OV-WI'], 'NP - '+item['NP'], 'NP-WI - '+item['NP-WI'], 'PAP - '+item['PAP'], 'PROC - '+item['PROC'], 'CPE - '+item['CPE'], 'ALLERGY - '+item['ALLERGY'], 'Vial Test - '+item['Vial Test'], 'PHY - '+item['PHY']];
                            pieValues = [parseInt(item['OV']), parseInt(item['OV-WI']), parseInt(item['NP']), parseInt(item['NP-WI']), parseInt(item['PAP']), parseInt(item['PROC']), parseInt(item['CPE']), parseInt(item['ALLERGY']), parseInt(item['Vial Test']), parseInt(item['PHY'])];

                            pieJson = [['OV - '+item['OV'],parseInt(item['OV'])], ['OV-WI - '+item['OV-WI'],parseInt(item['OV-WI'])], ['NP - '+item['NP'],parseInt(item['NP'])], ['NP-WI - '+item['NP-WI'],parseInt(item['NP-WI'])], ['PAP - '+item['PAP'],parseInt(item['PAP'])], ['PROC - '+item['PROC'],parseInt(item['PROC'])], ['CPE - '+item['CPE'],parseInt(item['CPE'])], ['ALLERGY - '+item['ALLERGY'],parseInt(item['ALLERGY'])], ['Vial Test - '+item['Vial Test'],parseInt(item['Vial Test'])], ['PHY - '+item['PHY'],parseInt(item['PHY'])]];

                        });

                        makePieChart(pieJson, pieLabels, pieValues, pieTitle);
                    }
                ); 

            }

        plot2.resetZoom();
    });

    function makePieChart(pieJson, pieLabels, pieValues, pieTitle)
    {

        piechart = $.jqplot('piechart', [pieJson], {
            title: pieTitle,
            seriesDefaults:{renderer:$.jqplot.PieRenderer, rendererOptions:{sliceMargin:0}},
            legend:{show:true,location:'e', xoffset:-155},
            cursor: {
                show:false,
                zoom:false,
                showVerticalLine:false,
                showHorizontalLine:false,
                showCursorLegend:false,
                showTooltip: false
            }
        });

        piechart.replot();            

        $("#piechart2").html('');

        var r = Raphael("piechart2");

        r.g.text(320, 70, pieTitle).attr({"font-size": 20});

        var pie = r.g.piechart(320, 240, 100, pieValues, {legend: pieLabels, legendpos: "east"});

        pie.hover(function () {
                this.sector.stop();
                this.sector.scale(1.1, 1.1, this.cx, this.cy);
                if (this.label) {
                    this.label[0].stop();
                    this.label[0].scale(1.5);
                    this.label[1].attr({"font-weight": 800});
                }
            }, function () {
                this.sector.animate({scale: [1, 1, this.cx, this.cy]}, 500, "bounce");
                if (this.label) {
                    this.label[0].animate({scale: 1}, 500, "bounce");
                    this.label[1].attr({"font-weight": 400});
                }
        });

        $("#piechart2").css("width", 700);
        $("#piechart2").css("height", 520);

    }

So let’s get to what all this actually does. When the page loads you see the line graph to start off.  Each line represents the number of patients seen per week per clinic per year.
Next, we want to drill down, so I’ll click on the highest point on the graph.  After playing with the jqPlot pie chart I also added the gRaphael pie chart for a comparison.  Let’s start with the jqPlot pie chart.  Each pie chart shows each type of patient visit for the week in question.

I added the subtotals to the legend to help decipher the slices.  As you can tell, jqPlot doesn’t order the slices by size so if you have problems with colors like I do, it’s hard to tell which slice goes with which total.  It’s especially bad with the slivers.  The jqPlot pie chart is not interactive.  I cannot click on the slices and enable further drill down of data.  Also, you can’t label the slices to help in reading the chart.

So let’s take a look at the gRaphael pie chart.  gRaphael uses SVG to generate it’s charts and graphs.  As you can see, there is a hover feature which causes the selected slice to pull out as well as label in the legend to become bold.  Also the slices are ordered in size so even without the hover option, the user can intuitively read the chart.  There is also a click() function, but the only unique identifier I have found so far is the label in the legend.  That will make it hard to get a value that can be passed back to the database to drill down further in the data.

So let’s wrap up.

  • The jqPlot line graph is great.  There are plenty of options I didn’t even use.  Another feature that I’m using in this chart but didn’t mention is the zoom feature.  So where lines cross, the user can zoom in and get a clearer picture.
  • The functionality of the jqPlot pie chart is lacking but I’m sure that with time it will be improved.
  • gRaphael has some of the bells and whistles that jqPlot doesn’t but how it stores the data points may limit how much I can extend it for our purposes.

So overall, I like both of these plugins and will be able to find a use for them in future projects.

One thought on “Visualizing Data – jqPlot & gRaphaël”

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>