Building a sortable (and clickable!) table with dc.js and crossfilter

Posted on Tags , , , ,

I’ve recently been playing around with dc.js to build some neat interactive data visualizations and dashboards to analyze the performance of machine learning models. The interactive data-slicing and visualizations enabled by dc.js and crossfilter are perfect for digging deep into any type of multi-dimensional data.  They help with gaining a more intuitive understanding of the data, and help me better understand the performance and deficiencies of different machine learning models.

One of the less “fancy” dc.js widgets is the dataTable. That isn’t meant as a criticism, just that it doesn’t look nearly as impressive out of the box as the slickly animated charts that you are likely accustomed to if you have used dc.js a fair bit. This of course is completely understandable since the goal of the dataTable class is to provide a flexible interface to an object that enables the generation of tables that can then be styled and tweaked per the user’s desires.

When dealing with a large amount of data, I had a simple wishlist for a dc.js based table that was responsive to all filtering events on the underlying crossfilter object:

  1. Decent aesthetics – easy enough to do by leveraging something like bootstrap if you don’t want to roll your custom CSS
  2. Ability to paginate the data table – Fortunately, there is already a functioning example on the dc.js site that I was able to leverage
  3. Ability to sort filtered records by columns by clicking the column headers. Clicking the same column header repeatedly should toggle between ascending and descending order of sorting
  4. Have the ability to attach custom callback functions to table rows (onclick) that can do more interesting things if needed
  5. And finally, the table needed to be responsive to all dc.js based filtering events

After spending some time working on it, I was able to implement a solution that I am quite happy with. You can play with the final version of the table below.

Filtered Records

Showing - of

You can find the entire code for this example at the following repository:

A working example on a separate page can be found here.

I should note that once you have tens of thousands of observations, the table might start to impact overall performance as it is constantly trying to recalculate the sorting across all filtered data while a filter is being applied on a dc.js chart. If this ends up becoming an issue, you may want to consider either:

  1. Disable sorting as this is the most expensive operation
  2. Use a debounce with a largish value within the table implementation so that it doesn’t start calculating the updated view till after a bunch of rapid fire filter callbacks are fired (typical when dragging filters across dc.js charts). This is likely the best solution since no one is particularly interested in real-time updates to tables as you drag filters across charts.