tabular data visualization with jqGrid and jQuery

In my post Data Scientist Makes Peace with Web Programming, I argued that web programming skills belong in data scientists’ repertoire. Essentially, my thesis went that data consumers primarily use web browsers to interact with data, so data scientists should develop proficiency with the medium. With that in mind, I’ll periodically showcase core web development techniques from a data scientist’s point of view.

Today I’ll demonstrate the presentation of tabular data within a web browser using the jqGrid jQuery plugin. I’ll also show how to set all the jqGrid display features (header names, number of columns, row data, etc.) from the server side. (The jqGrid documentation primarily details client-side configuration of these parameters).

jqGrid in action:

Here the web browser retrieves content from the server in a serialized format (e.g. JSON), and jqGrid organizes it into the nice display pictured above. Refreshing the table updates the data, provided the server sends updated JSON.

jqGrid doesn’t stop there though—if it did we would just use the table HTML tag instead to display our data—it provides automatic scrollbars, cell and row editing, non-scrolling headers, and many more features.

Demonstration Code

To make this work, we first load jQuery and jqGrid, and then create an HTML container for the table:

<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Transitional//EN

http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd>

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  <head>

    <link type="text/css" href="http://www.trirand.com/blog/jqgrid/themes/redmond/jquery-ui-1.8.1.custom.css" rel="Stylesheet" />
    <link type="text/css" href="/site_media/js/jqGrid/css/ui.jqgrid.css" rel="Stylesheet" />
    <script src="/site_media/js/jquery.js"></script>
    <script type="text/javascript" src="/site_media/js/jquery-ui-1.8.9.minilims.min.js"></script>

    <title>jqGrid Demonstration</title>

    <script src="/site_media/js/example/example.js"></script>
    <script src="/site_media/js/jqGrid/js/jquery.jqGrid.min.js" type="text/javascript"></script>

  </head>

  <body>
    <div id="example_container">
      <table id="example_container_table"></table>
    </div>
  </body>
</html> 

We then activate the jqGrid table with JavaScript:

$(document).ready(function(){

    // Get the serialized table data and store it in the variable "data".
    $.getJSON('example/', function(data) {

$('#example_container_table').jqGrid({

   // Instruct jqGrid to read the serialized data as JSON
   datatype: "json",

   // Initialize the column model from the JSON-retrieved content.
   colNames: data.colNames,
   colModel: data.colModel,

   // Initialize the caption from the JSON-retrieved content.
   caption: data.caption,

   // Allow an unlimited number of rows on the screen at one time.
   rowNum: -1,

   // Miscellaneous settings
   viewrecords: true,
   width: 367,
   height: 300,
   shrinkToFit: false
});

//Populate the rows from the JSON-retrieved content.
$('#example_container_table')[0].addJSONData(data);
    });
});

Notice that we do not need to set the “url” property since the $.getJSON call retrieves the data and the addJSONData() function populates the rows with it.

Finally, on the server side we provide code to deliver the content in JSON format. In Django this looks like:

from django.http import HttpResponse
from django.utils.simplejson import dumps

def example(request):
  data = {'page' : 1, 'total' : 1, 'rows' : []} 
  row_data_list = [
    (3,1,'A',0.59),
    (3,1,'B',0.66),
    (3,1,'C',0.3),
    (3,1,'D',0.43),
    (3,1,'E',0.43),
    (3,1,'F',0.37),
    (3,1,'G',0.3),
    (3,1,'H',0.36),
    (3,1,'I',0.54),
    (3,2,'A',0.22),
    (3,2,'B',0.65),
    (3,2,'C',1.0),
    (3,2,'D',0.38),
    (3,2,'E',0.78),
    (3,2,'F',0.29),
    (3,2,'G',0.22),
    (3,2,'H',0.07),
    (3,2,'I',0.38),
    (3,3,'A',0.38),
    (3,3,'B',0.78),
    (3,3,'C',0.26),
    (3,3,'D',0.43),
    (3,3,'E',0.98),
    (3,3,'F',0.33),
    (3,3,'G',0.22),
    (3,3,'H',0.1),
    (3,3,'I',0.51),
    (4,1,'A',0.45),
    (4,1,'B',1.0),
    (4,1,'C',0.29),
    (4,1,'D',0.32),
    (4,1,'E',0.45),
    (4,1,'F',0.42),
    (4,1,'G',0.23),
    (4,1,'H',0.32),
    (4,1,'I',0.52),
    (4,2,'A',0.67),
    (4,2,'B',0.46),
    (4,2,'C',0.31),
    ]

  for index, row in enumerate(row_data_list):
    row_data = {
      'id' : 'row_number_' + str(index),
      'cell' : row
      }
    data['rows'].append(row_data)

  data['colNames'] = ['Window Size', 'Method', 'Group', 'Classifier Score']
  data['colModel'] = [
    {'name' : 'Window Size', 'index' : 'Window Size', 'width' : 130, 'align' : 'center'},
    {'name' : 'Method', 'index' : 'Method', 'width' : 50, 'align' : 'center'},
    {'name' : 'Group', 'index' : 'Group', 'width' : 50, 'align' : 'center'},


    {'name' : 'Classifier Score', 'index' : 'Classifier Score', 'width' : 120, 
     'align' : 'center', 'formatter' : 'number', 'formatoptions' : {'decimalPlaces' : 2}
     },
    ]

  data['caption'] = 'Simulation Results'

  response = HttpResponse(dumps(data), mimetype='application/json')
  response['Cache-Control'] = 'no-cache'
  return response

The urls.py file that calls this function contains:

from django.conf.urls.defaults import *
from django.views.generic.simple import direct_to_template

from minilims.example.views import *

urlpatterns = patterns (
  '',
  (r'^$', direct_to_template, {'template': 'example/index.html'}),
  (r'example/$', example, {}),
  )
This entry was posted in data science and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published.

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>