dcsimg

Bring Your Data to Life with D3.js

By Rob Gravelle

WEBINAR:
On-Demand

Building the Right Environment to Support AI, Machine Learning and Deep Learning


Let's face it, raw data is boring. Moreover, it can be a challenge to spot patterns in reams of textual format. Visuals are far easier to interpret. Humans tend to be visual by nature, so putting data in a graphical context makes it much easier to spot trends.

There are a few data visualization libraries, but one in particular that has been gaining a lot of traction of late is D3. Short for Data-Driven Documents, D3 is a JavaScript library for producing dynamic, interactive data visualizations in any web browser. It makes use of the widely implemented SVG, HTML5, and CSS standards. In contrast to many other libraries, D3.js gives you tremendous control over the final result.

In today's tutorial we'll use the D3.js library to display the contents of a CSV data file within a dynamically generated HTML table.

Loading the Data

Our data is a CSV dump of the films from the Sakila Sample Database. It's one of my favorite data sources because its content is entertaining as heck!

 

"film_id","title","description","release_year","rental_rate","length","rating" "1","ACADEMY DINOSAUR","A Epic Drama of a Feminist And…","2006","0.99","86","PG" "47","BABY HALL","A Boring Character Study of a A Shark And a Girl who must…","2006","4.99","153","NC-17" "110","CABIN FLASH","A Stunning Epistle of a Boat And a Man who…","2006","0.99","53","NC-17"

D3's d3-fetch module provides convenient parsing on top of the whatwg Fetch spec. It includes Ajax-powered methods for retrieving data in a variety of formats, from text and csv to blobs, images, json, and whatever data types you might want to load.

For example, d3.csv() converts the raw data into an array of objects:

d3.csv("sakila_videos.csv").then(function(data) {
  console.log(data[0]); /* => {
                             film_id: "1", 
                             title: "ACADEMY DINOSAUR", 
                             description: "A Epic Drama of a Feminist And…", 
                             release_year: "2006", 
                             rental_rate: "0.99", 
                             length: "86",
                             rating: "PG"
                           } */
});

What if you don't want an array of objects? Another option is to use the d3.text() method. It treats the data as a string:

d3.text("sakila_videos.csv").then(function(data) {
  console.log(data); 
/* 
"film_id","title","description","release_year","rental_rate","length","rating"
"1","ACADEMY DINOSAUR","A Epic Drama of a Feminist And…","2006","0.99","86","PG"
"47","BABY HALL","A Boring Character Study of a A Shark And a Girl who must…" etc…
*/
});

From there, we can use the d3.csvParseRows(). It converts the CSV string into an array (rows) of arrays (columns):

d3.text("sakila videos.csv").then(function(data) {
  var rows  = d3.csvParseRows(data);
  console.log(rows);
/*
0:Array(7)
  0:"film_id"
  1:"title"
  2:"description"
  3:"release_year"
  4:"rental_rate"
  5:"length"
  6:"rating"
1:Array(7)
  0:"1"
  1:"ACADEMY DINOSAUR"
  2:"A Epic Drama of a Feminist And…"
  3:"2006"
  4:"0.99"
  5:"86"
  6:"PG"
2:Array(7)
0:"47"
1:"BABY HALL"
2:"A Boring Character Study of a A Shark And a Girl who…"
3:"2006"
4:"4.99"
5:"153"
6:"NC-17"
etc…
*/
});

Rendering the Table and Headers

You'll find that working in HTML format with D3 is very similar to jQuery. D3 has a select() method for selecting a single DOM element as well as a style() method for…er…styling elements.

Here's the code for appending the table to the DOM:

var rows  = d3.csvParseRows(datasetText),
    table = d3.select('body').append('table')
    .style("border-collapse", "collapse")
    .style("border", "2px black solid");

With a reference to the table, we can now add the headers:

// headers
table.append("thead").append("tr")
    .selectAll("th")
    .data(rows[0])
    .enter().append("th")
    .text(function(d) { return d; })
    .style("border", "1px black solid")
    .style("padding", "5px")
    .style("background-color", "lightgray")
    .style("font-weight", "bold")
    .style("text-transform", "uppercase");

An Explanation of some of the Above Methods

There are a lot of method calls in the above code snippet, some of which require further elucidation:

  • selection.selectAll(selector): Selects the descendant elements that match the specified selector string for each selected element - similar to jQuery find().
  • selection.data([data[, key]]): Joins the specified array of data with the selected elements, returning a new selection that represents the updated selection.
  • selection.enter(): Identifies any DOM elements that need to be added when the joined array is longer than the selection. It's defined on an update selection (i.e., the selection returned by .data() ):
  • selection.text([value]): Sets the text content to the specified value on all selected elements, replacing any existing child elements. If the value is a constant, then all elements are given the same text content. The method can also accept a function, in which case the value is evaluated for each selected element, in order, being passed the current method call (d). The function's return value is then used to set each element's text. Meanwhile, a null (or no) value clears the content.

Appending the Data Rows

The exact process that we followed to add the headers can again be applied to the data rows:

// data
table.append("tbody")
    .selectAll("tr").data(rows.slice(1))
    .enter().append("tr")
    .selectAll("td")
    .data(function(d){return d;})
    .enter().append("td")
    .style("border", "1px black solid")
    .style("padding", "5px")
    .text(function(d){return d;})
    .style("font-size", "12px");

Here is the final product in Codepen. Note that it includes mouseover cell highlighting(!):

Going Forward

In today's tutorial we used the D3.js library to display the contents of a CSV data file within a dynamically generated HTML table. In the next article, we'll get a taste for D3's SVG prowess by constructing a slick stock chart.



Rob Gravelle

Rob Gravelle resides in Ottawa, Canada. His design company has built web applications for numerous businesses and government agencies. Email him.

Rob's alter-ego, "Blackjacques", is an accomplished guitar player, who has released several CDs and cover songs. His band, Ivory Knight, was rated as one of Canada's top hard rock and metal groups by Brave Words magazine (issue #92).



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.

    By submitting your information, you agree that htmlgoodies.com may send you HTMLGOODIES offers via email, phone and text message, as well as email offers about other products and services that HTMLGOODIES believes may be of interest to you. HTMLGOODIES will process your information in accordance with the Quinstreet Privacy Policy.

  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date