Blog

Jan 11, 2017  mode_comment

Drawing a bar chart with d3.js for JS beginners (Part I)

Back

D3.js is a powerful data visualizing JavaScript (JS) library developed by Mike Bostock. There are numerous amazing d3.js tutorials out there, but I wanted to outline some elementary steps for my learning experience and hopefully help others like me who are new to both JS and d3.js.


1. Download d3.js

Before we go into any coding, let's first download the d3.js library.
You can download any version, but I downloaded version 3.5.17 because I have found that using version 4 of d3.js may be a bit more confusing for d3.js/JS beginners (like me) because there aren't a lot of d3.js tutorials written in version 4 yet (and you want to utilize all those awesome d3.v3 tutorials out there!). Once you download the file, you can include the library in your HTML document with the following code:

<script type="text/javascript" src="../d3/d3.js"></script>

Make sure that src="<your dir>" specifies the directory where the d3.js library is downloaded. Alternatively, you can link the library directly from the web with the following code:

<script src="https://d3js.org/d3.v4.min.js"></script>


2. Bind Data

Before diving into learning how to bind data, let's first familiarize ourselves with the d3 chaining method:

d3.select("body").append("p").text("New paragraph!");

This d3 code selects your <body> html element, appends the element <p>, and inserts the text "New paragraph!" to the parent element it's being called on (the element <p>).
The above d3 code is also equivalent to the code below, written in vanilla JS style:

var body = d3.select("body");
var p = body.append("p");
p.text("New paragraph!");

In plain JS, elements are typically dealt with one at a time, but by utilizing d3 chaining, we are able to merge the 3 lines of code into 1, which makes our lives easier and our code more visually appealing. Let's say we have an array of numbers as our data.

var data_array = [1, 5, 7, 3, 9];

Now we are going to bind this data:

d3.select("body").selectAll("p")
    .data(data_array)
    .enter()
    .append("p")
    .text("I am some text");

There are 3 things to notice here. First, we now selectAll("p"), bind our data .data(data_array), and .enter()
The first two seem intuitive, but why do we need to include .enter() in our chain of commands? That is because we have to remember that we initially do not have any <p> elements in our HTML code.
When working with real life data, we generally don't know the size of the data set we will be working with and often the number of observations in the dataset is large. Thus, for a dataset like our data_array, it may not be a big deal to start with an HTML document manually written like this:

<body>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <p></p>
</body>

But as the dataset grows larger and larger, this task becomes exponentially more difficult and annoying.
This is why we start with a blank HTML body element, select the body element with .select("body"), pseudo-select the <p> elements using .selectAll("p"), count/parse the data using .data(data_array), create a place-holder for the new data-bound elements with .enter(), in this case, 5 place-holders, and finally, append <p> elements with the text attribute to the place-holders.

Output of the above d3 code

That was a lot of information, but we are not quite done yet. Some of you may be wondering by now "how come we are giving our data-bound <p> elements a text attribute when we already bound it with our numerical data?"
That is because the data is bound to the <p> elements' __data__ attribute and we need to make an extra step to actually use the data.

1 is set as the first paragraph's data attribute

This is where a little JS knowledge becomes important. Whenever .data() is called in d3, we can create an anonymous function in JS that comes after .data(), and this function will accept the data for further actions.
Here is an example of a function in JS:

var myFunction = function(var1) {
    //some command
    return var1; // returns the variable var1
}

var myFunction creates the variable myFunction and = function(var1){} tells to define a function that takes a variable called var1 (you can name it however you like) for the variable myFunction.
Declaring a function without the var myFunction makes the function anonymous but the function behaves the same. Now let's use this in our d3 code.

d3.select("body").selectAll("p")
    .data(data_array)
    .enter()
    .append("p")
    .text(function(value){ return value; });
Now we have our data displayed!

As explained, the anonymous JS function function(value) { return value; } took our data_array values and returned the values for printing because it was called after the .data(data_array) method.
We finally have our data displayed in some sensible format! For more information on JavaScript functions, please look at chapter 3 in this Awesome, Awesome, FREE, interactive e-book on JavaScript!


3. Wrapping up part 1

We are done with part 1 of making a bar chart with d3.js! Thanks for following. In this post, I explained how to install the d3.js library and went over some d3 and JS basics needed to work with data. I tried my best to address some struggles and confusions I went through when I was teaching myself all of this and I hope this post could help others who may have similar difficulties as I did. In the next post, I'll go over how to read a .csv file using d3 and the basics of creating a bar chart using that data!


About

I am a computational scientist finishing my PhD at U of Penn. I picked up programming coming into graduate school and after years of computational research, I'm amazed by what data can do. I love to use data analytics to find trends, which when exposed, empower people to make informed decisions about the world they live in. I'm also the co-founder of Penn Data Science Group.