Home > Code, Graphics, Interactive, Tutorial > Remaking a Washington Post graph, part 1

Remaking a Washington Post graph, part 1

This is the first part of a tutorial for making a graph like this one on the Washington Post website. My clone of the graph will use RaphaëlJS, and unfortunately my clone doesn’t yet work in Internet Explorer; it should work fine in any other browser.

You can see the cloned graph here.

Who’s this tutorial meant for? It’s aimed at people who already know the basics of JavaScript, who have little or no experience with making visualizations from scratch, and who haven’t used RaphaëlJS. Chances are, this tutorial will sometimes be too basic, and sometimes assume too much. I apologize in advance. If you have any questions, I’d be happy to try to answer them.

One more thing. This tutorial will cover how I made my graph. There may be cleaner or quicker ways to do some of this. Corrections are welcome.

Step 0:

For this step, you need to get raphael-min.js, from here (from the “download” link in the upper right).

Once you have raphael-min.js, we’ll start with this basic html file:

<html>
    <head>
        <title>Washington Post graph clone</title>
        <script src="raphael-min.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript" charset="utf-8">
			window.onload = function () {
				// Raphael stuff will go here
			};
        </script>
    </head>
    <body>
        <div id="graph"></div>
    </body>
</html>

We have some CSS at the top in the style tags, two sets script tags—one for including raphael-min.js, and one where we’ll put all of our code—and the body, with one div.

Probably all of this is clear, except the reason for the graph div (if you haven’t used RaphaëlJS). RaphaëlJS will need a div in which to do its thing.

Step 1: Get the data

Actually, you can just download my version of the data in this JavaScript file, so there’s not much to do here. It will probably help to know how I reformatted the data, though, so read on.

The first task, if you’re going to get the data yourself, is locating it. If you go to the original graph’s website, and look at the source code, search for “debt.js”. The data is in that file, in the block of code between (and including) “dates” on the fourth line, and the “other_billions” array on line 48. Actually, you can skip “other_billions” and delete “australia_billions” if you want; we won’t be using these.

After pulling this out, I reformatted the data into JavaScript objects within objects. Look at my version of the data file to see what I mean. In the original, each separate type of data is in an array. In my version, there’s an array for dates, and the debt numbers are arranged in an object. Within that, there’s an object for each continent. Then, within the continent object there are arrays for total, and, except for Australia and “Other countries”, there are arrays for each country in the continent. Confused? Let me give you an example.

To get the array of debt numbers for all of Asia, you would use

debt["Australia"]["total"]

or

debt.Australia.total

For Australia, you would use

debt["Australia"]["total"]

(thinking of Australia as a continent rather than a country).

For Japan’s numbers, use

debt["Asia"]["Japan"]

Formatting the data like this has two advantages. First, it makes the data much easier to interpret for any human reader of the file. Second, it’ll help us write cleaner and clearer code.

There’s still one problem with this data, which leads to …

Step 2: Modifying the data

Unfortunately, the data is not in consistent units. There’s a comment in the second line of the data, pointing out that the numbers are sometimes in billions and sometimes in trillions. This seems like a bad idea to me. If we keep the data in this form, we’ll have to write our code to treat numbers differently every time the scale matters.

So, let’s put all of the totals in trillions. Fortunately, the comment tells us exactly which values we need to change.

Here’s a function to change all of the billions to trillions. It’s meant to act on my version of the data, not the original.

function rescaleData() {
	for (attr in debt) {
		if (debt.hasOwnProperty(attr) 
		  && attr !== "Asia" 
		  && attr !== "Europe" 
		  && attr !== "Australia" 
		  && attr !== "Other") {
			for (subattr in debt[attr]) {
				if (debt[attr].hasOwnProperty(subattr) && subattr !== "total") {
					for(var i = 0; i < numMonths; i++) {
						debt[attr][subattr][i] = debt[attr][subattr][i]/1000;
					}
				}
			}
		}
	}
}

Here’s an explanation: The function looks through all of the continents one by one (in this tutorial, I’m going to say that “Other” is a continent). If the current continent is one of those that is already in trillions, it skips it. Otherwise, it looks within the continent, skips the “total” array (which is already in trillions), and continues on to country arrays. When it gets to a country array, it changes the array values one-by-one, dividing them by 1000 (since X billion = X/1000 trillion).

Step 3: Choosing dimensions

Now we have to start making some choices about how the graph will look. Since we’re just trying to make a graph like the Washington Post graph, many preliminary choices are made for us (like, What form of graph will we use?). However, we still need to make some specific choices about how the data will be represented, like how wide and tall to make the graph, where to put tick marks, and especially, how to transform the debt values into screen measurements. How tall should $1 billion be? (We could try to make everything match the original, but that’s more work than I want to do.)

First, how wide and tall. I just picked some numbers: 800 pixels wide and 900 tall for the outside dimensions. For the inner dimensions (where the shaded areas are, rather than tick marks and such), I chose 700 wide and 800 tall. This will give some room for the x- and y-axes. Also, it’ll help to have a variable for the number of months in the data. Finally, we’ll want to choose where the left-most edge of the graph is, which I’ll call xintercept, and where the bottom is, which I’ll call yintercept.

Here now is how the entire html document looks, including the function that rescales some of the data:

(Correction: We need to include the data, of course, so I’ve added a line to do that, line 5.)

<html>
    <head>
        <title>Washington Post graph clone</title>
        <script src="raphael-min.js" type="text/javascript" charset="utf-8"></script>
        <script src="wapo-data.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript" charset="utf-8">
		window.onload = function () {
			var width = 900;
			var height = 800;
			var xintercept = 40;  // left side of graph, or, the x-position of the first month
			var yintercept = 750; // bottom of the graph, or, the y-position of zero debt
			var graphInnerHeight = 700;
			var graphInnerWidth = 800;
			var numMonths = 134;

			function rescaleData() {
				for (attr in debt) {
					if (debt.hasOwnProperty(attr) 
					  && attr !== "Asia" 
					  && attr !== "Europe" 
					  && attr !== "Australia" 
					  && attr !== "Other") {
						for (subattr in debt[attr]) {
							if (debt[attr].hasOwnProperty(subattr) && subattr !== "total") {
								for(var i = 0; i < numMonths; i++) {
									debt[attr][subattr][i] = debt[attr][subattr][i]/1000;
								}
							}
						}
					}
				}
			}

			rescaleData(); // do the rescaling
		};
        </script>
    </head>
    <body>
        <div id="graph"></div>
    </body>
</html>

Next time

In the next post, we’ll make scales to translate data amounts into screen lengths (How tall should $1 billion be?). After that, we have to figure out how exactly to draw the shapes we need, and then finally we’ll have something to see.

About these ads
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: