Google Charts and CSV Part 3: Side-by-Side Bubble Charts

Introduction

If you haven’t already, go ahead and take a look at the previous two installments of this series (Easy Data Visualization with Google Charts and a CSV and More Google Charts with a CSV: Bubble Charts). Today we’re going to take the bubble chart from More Google Charts with a CSV: Bubble Charts and add another chart to the same page. It’s not exactly as simple as duplicating all the code we created last time, but it nearly is.

Setup

Begin by downloading the finished product from last time here. Also, I’ve pasted the HTML below in case that’s easier for you:

<!DOCTYPE html> <html> <head> <title>Google Chart Example</title> <style> ul {list-style-type: none;} </style> <script src="https://www.google.com/jsapi"></script> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="jquery.csv-0.71.js"></script> <script> // load the visualization library from Google and set a listener google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawChart); function drawChart() { // grab the CSV $.get("kzn1993.csv", function(csvString) { // transform the CSV string into a 2-dimensional array var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}); // use arrayData to load the select elements with the appropriate options for (var i = 0; i < arrayData[0].length; i++) { // this adds the given option to both select elements $("select").append("<option value='" + i + "'>" + arrayData[0][i] + "</option"); } // set the default selection $("#domain option[value='0']").attr("selected","selected"); $("#range option[value='1']").attr("selected","selected"); // this new DataTable object holds all the data var data = new google.visualization.arrayToDataTable(arrayData); // this view can select a subset of the data at a time var view = new google.visualization.DataView(data); view.setColumns([{calc:stringID, type: "string"},1,2,3]); // this function returns the first column values as strings (by row) function stringID(dataTable, rowNum){ // return dataTable.getValue(rowNum, 0).toString(); // return an empty string instead to avoid the bubble labels return ""; } var options = { title: "KwaZulu-Natal Household Survey (1993)", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, bubble: {stroke: "transparent", opacity: 0.2}, colorAxis: {colors:['red','blue']}, }; var chart = new google.visualization.BubbleChart(document.getElementById('chart')); chart.draw(view, options); // set listener for the update button $("select").change(function(){ // determine selected domain and range var domain = +$("#domain option:selected").val(); var range = +$("#range option:selected").val(); var color = +$("#color option:selected").val(); var size = +$("#size option:selected").val(); // update the view view.setColumns([{calc:stringID, type: "string", label: "Household ID"},domain,range,color,size]); // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; options.bubble = {stroke: "transparent", opacity: 0.2}; options.colorAxis = {colors:['red','blue']}; // update the chart chart.draw(view, options); }); }); } </script> </head> <body> <div id="chart" style="width:800px; height:500px;"> </div> <ul> <li> Y-Axis <select id="range"></select> </li> <li> X-Axis <select id="domain"></select> </li> <li> Color <select id="color"></select> </li> <li> Size <select id="size"></select> </li> </ul> </body> </html> 

Data

For this tutorial I’ve split the South African data by province in 1993. File kz1993.csv contains only the households in the former KwaZulu bantustan. File n1993.csv contains only the black households in the Natal province of what was at the time “white” South Africa. For more details on the data, please see the first tutorial in this series (Easy Data Visualization with Google Charts and a CSV).

HTML

Let’s begin by modifying the HTML. First we’ll encapsulate both the chart and the list in a <div> that is floated to the left. We also need to add a class (I’m going to choose chart) to each of the <select> elements to distinguish the chart on the left from the one on the right:

 <div style="float:left;"> <div id="chart" style="width:600px; height:500px;"> </div> <ul> <li> Y-Axis <select class="chart" id="range"></select> </li> <li> X-Axis <select class="chart" id="domain"></select> </li> <li> Color <select class="chart" id="color"></select> </li> <li> Size <select class="chart" id="size"></select> </li> </ul> </div> 

So far so good. Now copy this entire <div> and paste a duplicate below. Change the ids and classes for this <div> by adding a 2. Also change the float direction to “right“:

 <div style="float:right"> <div id="chart2" style="width:600px; height:500px;"> </div> <ul> <li> Y-Axis <select class="chart2" id="range2"></select> </li> <li> X-Axis <select class="chart2" id="domain2"></select> </li> <li> Color <select class="chart2" id="color2"></select> </li> <li> Size <select class="chart2" id="size2"></select> </li> </ul> </div> 

JavaScript

Chart 1

Now we need to make some adjustments to our drawChart() callback function. First we’ll change the CSV file reference from the kzn1993.csv to kz1993.csv.

 function drawChart() { // grab the first CSV $.get("kz1993.csv", function(csvString) { 

In the for loop we need to change the jQuery selection of all select elements to only those with the chart class:

 // use arrayData to load the select elements with the appropriate options for (var i = 0; i < arrayData[0].length; i++) { // this adds the given option to both select elements $("select.chart").append("<option value='" + i + "'>" + arrayData[0][i] + "</option>"); } 

The last change we need to make for the chart on the left is to modify the title:

 var options = { title: "KwaZulu-Natal Household Survey (1993) - KwaZulu", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, bubble: {stroke: "transparent", opacity: 0.2}, colorAxis: {colors:['red','blue']}, }; 

Chart 2

Now, for the chart on the right we can start by copying the $.get(); call of the first chart. We just need to change the referenced CSV, the referenced HTML ids and classes, and the title. First, change the referenced CSV:

 // grab the second CSV (this one covers Natal Province) $.get("n1993.csv", function(csvString) { 

Next, change the referenced ids and classes here:

 // use arrayData to load the select elements with the appropriate options for (var i = 0; i < arrayData[0].length; i++) { // this adds the given option to both select elements $("select.chart2").append("<option value='" + i + "'>" + arrayData[0][i] + "</option>"); } // set the default selection $("#domain2 option[value='0']").attr("selected","selected"); $("#range2 option[value='1']").attr("selected","selected"); 

and here:

 var chart = new google.visualization.BubbleChart(document.getElementById('chart2')); chart.draw(view, options); // set listener for the update button $("select.chart2").change(function(){ // determine selected domain and range var domain = +$("#domain2 option:selected").val(); var range = +$("#range2 option:selected").val(); var color = +$("#color2 option:selected").val(); var size = +$("#size2 option:selected").val(); 

The last thing to do is change the title:

 var options = { title: "KwaZulu-Natal Household Survey (1993) - Natal", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, bubble: {stroke: "transparent", opacity: 0.2}, colorAxis: {colors:['red', 'blue']}, }; 

Conclusion

The end result looks pretty nice (if your charts stack vertically, you need to make your charts smaller or your screen wider). side_by_side To play around with a live version go here. If any of this was confusing, please check the previous two tutorials (Easy Data Visualization with Google Charts and a CSV and More Google Charts with a CSV: Bubble Charts) or leave a comment below.

More Google Charts with a CSV: Bubble Charts

Last time we built an interactive scatter plot. This time we’re going to turn that scatter plot into a bubble chart (see a preview of the finished product here). Start by openning up the HTML document we created last time. You can see the source here or expand the section below:

 <!DOCTYPE html> <html> <head> <title>Google Chart Example</title> <script src="https://www.google.com/jsapi"></script> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="jquery.csv-0.71.js"></script> <script> // load the visualization library from Google and set a listener google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawChart); function drawChart() { // grab the CSV $.get("kzn1993.csv", function(csvString) { // transform the CSV string into a 2-dimensional array var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}); // use arrayData to load the select elements with the appropriate options for (var i = 0; i < arrayData[0].length; i++) { // this adds the given option to both select elements $("select").append("<option value='" + i + "'>" + arrayData[0][i] + "</option"); } // set the default selection $("#domain option[value='0']").attr("selected","selected"); $("#range option[value='1']").attr("selected","selected"); // this new DataTable object holds all the data var data = new google.visualization.arrayToDataTable(arrayData); // this view can select a subset of the data at a time var view = new google.visualization.DataView(data); view.setColumns([0,1]); var options = { title: "KwaZulu-Natal Household Survey (1993)", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, legend: 'none' }; var chart = new google.visualization.ScatterChart(document.getElementById('chart')); chart.draw(view, options); // set listener for the update button $("select").change(function(){ // determine selected domain and range var domain = +$("#domain option:selected").val(); var range = +$("#range option:selected").val(); // update the view view.setColumns([domain,range]); // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; // update the chart chart.draw(view, options); }); }); } </script> </head> <body> <div id="chart" style="width:800px; height:500px;"> </div> <select id="range"></select> <select id="domain"></select> </body> </html> 

Add Controls for Size and Color

Bubble charts add two dimension, size and color, to the standard scatter plot (here I’m using Google’s terminology, several other graphics libraries simply add this functionality to their scatter plot functions). To keep the nice interactivity we built into our last chart, let’s start by adding controls for the color and size. We’ll nest everything in an unordered list and add labels to the controls. Just change the section with two <select> tags to match the following:

 <ul> <li> Y-Axis <select id="range"></select> </li> <li> X-Axis <select id="domain"></select> </li> <li> Color <select id="color"></select> </li> <li> Size <select id="size"></select> </li> </ul> 

Next we want to get rid of the bullets in our unordered list. Add the following <style> tag inside your <head> tag.

 <style> ul {list-style-type: none; } </style> 

Changing the Chart Type

Change the line that loads the chart object from this:

 var chart = new google.visualization.ScatterChart(document.getElementById('chart')); 

to this:

 var chart = new google.visualization.BubbleChart(document.getElementById('chart')); 

Feeding the Data to the Chart

The data table for Google’s bubble chart requires the first coloumn to be a string which can be used to identify the bubbles. When we loaded the CSV into an array in the last tutorial, we parsed all values as scalars. We need to update our DataView call to change the values in the first column, the household ids (hhid), to string. This requires us to add a function to retrieve these strings from the DataTable.

 var view = new google.visualization.DataView(data); view.setColumns([{calc:stringID, type: "string"},1,2,3]); // this function returns the first column values as strings (by row) function stringID(dataTable, rowNum){ return dataTable.getValue(rowNum, 0).toString(); } 

Updating the Chart

Now we need to modify the code that updates the chart when a user changes the selected variables. First we’ll add local variables for color and size to the <select> listener function. These variables need to be assigned the value of the respective <select> tag. After we have column indices for color and size, we will set these as the third and fourth columns (after the id column) in our bubble chart view. See the highlighted lines below:

 $("select").change(function(){ // determine selected domain and range var domain = +$("#domain option:selected").val(); var range = +$("#range option:selected").val(); var color = +$("#color option:selected").val(); var size = +$("#size option:selected").val(); // update the view view.setColumns([{calc:stringID, type: "string"},domain,range,color,size]); // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; // update the chart chart.draw(view, options); }); 

Unfortunately, when I test this and select a few variables of interest I get the following chart. This is not very useful. The id values obscure all the information. bubble1

Improving Upon the Defaults

Removing the Bubble Label

The bubble labels would work fine if we had only a few data points and being able to quickly identify them was important. In this case, we are more interested in the general relationships between the variables and not the specific position of any one household. Let’s start by removing the bubble label. Go to our stringID function and return an empty string instead of the household id (be sure to comment out the old return statement):

 function stringID(dataTable, rowNum){ // return dataTable.getValue(rowNum, 0).toString(); // return an empty string instead to avoid the bubble labels return ""; } 

Now let’s check our chart: bubble2

Removing the Bubble Border and Adjusting Bubble Opacity

Okay. This is a lot nicer, but we can do better by removing the bubble borders and lowering the bubble opacity, since both cause issues with occlusion (i.e., there is data we are not seeing due to overly opaque data in the foreground). To remove the bubble’s border we’ll set it’s stroke color to “transparent”. Let’s change the opacity from the default of 0.8 to 0.2. To implement this we need to add an element to our initial options object

 var options = { title: "KwaZulu-Natal Household Survey (1993)", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, bubble: {stroke: "transparent", opacity: 0.2}, }; 

and reset it in our <select> listener function:

 // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; options.bubble = {stroke: "transparent", opacity: 0.2}; 

Let’s take a look: bubble3

Changing the Color Gradient

This is starting to look great. One issue I have with the default color choice, besides being ugly, is that gray with an opacity of 0.2 is hard to see. Let’s make the color gradient change from red to blue. We do this again by adding an element to the initial options object

 var options = { title: "KwaZulu-Natal Household Survey (1993)", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, bubble: {stroke: "transparent", opacity: 0.2}, colorAxis: {colors:['red','blue']}, }; 

and resetting it in our <select> listener function:

 // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; options.bubble = {stroke: "transparent", opacity: 0.2}; options.colorAxis = {colors:['red','blue']}; 

Bam! And here’s our finished product: bubble4 These changes have made it easier to explore the dataset and added a little style in the process. You can find an interactive version here (check the source if you are having problems with your chart).

Conclusion

While this ramped up the complexity of our figure (compared to the chart from the previous tutorial), being able to change which variables control the color and size of the bubbles will make your data that much more engaging. Take the source, change the reference to your CSV, and remember to download a copy of the jquery-csv script. With just a few steps you can have your own interactive chart to encourage your site’s viewers to explore your data. Check out the next tutorial in this series: Google Charts and CSV Part 3: Side-by-Side Bubble Charts For more information on Google’s bubble chart, check the documentation here.

Easy Data Visualization with Google Charts and a CSV

Static figures work fine for a print publication. However, when you want to present your research or collected data online, static is stale and dynamic is alive. Today we’re going to take a CSV and create a simple, but interactive, scatter plot. This tutorial assumes some basic familiarity with HTML and JavaScript. If you don’t currently possess these skills, head on over to Codecademy and follow the Web Fundamentals track and the JavaScript track.

Setting Up

To begin, we need to make sure we have the CSV we want to load and the JavaScript library jquery-csv in the same folder as our HTML.

Preview and Data

Here’s the end result of this tutorial: Finished Chart The data I’ll be using is from the three wave KwaZulu-Natal Income Dynamics Study (KIDS). In this example I will be using the first round of the survey (1993). Children are household members listed as younger than 16 and pensioners are defined as males over 65 and females over 60. I use an adult equivalent measure of household income used by Carter and May (1999) and many others in the South African context. The cleaned CSV can be downloaded here. I recommend you download this CSV to work along with this tutorial, but feel free to use your own (just be careful to make the relavent changes to the example code). Add the CSV to the same folder as the HTML we will be creating.

jQuery-CSV

The jQuery-CSV library allows us to easily take a string of CSV data and transform it into the appropriate format for Google’s visualization library. Download either jquery.csv-0.71.js or jquery.csv-0.71.min.js from that page and add it to the folder where your HTML will go.

Accessing the CSV

To begin with, create the HTML document, load the Google JS API, jQuery, and the jQuery library, and display the contents of the CSV to confirm the CSV is where it’s supposed to be and that we can access all the JavaScript we need:

 <!DOCTYPE html> <html> <head> <title>Google Chart Example</title> <script src="https://www.google.com/jsapi"></script> <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> <script src="jquery.csv-0.71.js"></script> <script> // wait till the DOM is loaded $(function() { // grab the CSV $.get("kzn1993.csv", function(csvString) { // display the contents of the CSV $("#chart").html(csvString); }); }); </script> </head> <body> <div id="chart"> </div> </body> </html> 

Load your newly created HTML to confirm your code outputs the contents of the CSV.

A Simple Scatter Plot

Clear the script tag we used to display the CSV; in this section we will focus on the JavaScript necessary to create a scatter plot with our CSV. Start by loading the visualization library and setting a callback function:

 // load the visualization library from Google and set a listener google.load("visualization", "1", {packages:["corechart"]}); google.setOnLoadCallback(drawChart); 

Next, we need to create the callback function we referenced in the previous step. We’ll begin by grabbing the CSV as we did previously:

 function drawChart() { // grab the CSV $.get("kzn1993.csv", function(csvString) { 

We need to transform the CSV into a format suitable for Google’s visualization library:

 // transform the CSV string into a 2-dimensional array var arrayData = $.csv.toArrays(csvString, {onParseValue: $.csv.hooks.castToScalar}); 

Next, we’ll transform this array into a DataTable object:

 // this new DataTable object holds all the data var data = new google.visualization.arrayToDataTable(arrayData); 

Since we have more columns of data than are needed for our visualization, let’s create a view on this table of just the first two columns:

 // this view can select a subset of the data at a time var view = new google.visualization.DataView(data); view.setColumns([0,1]); 

Now let’s set some basic options for our chart:

 var options = { title: "KwaZulu-Natal Household Survey (1993)", hAxis: {title: data.getColumnLabel(0), minValue: data.getColumnRange(0).min, maxValue: data.getColumnRange(0).max}, vAxis: {title: data.getColumnLabel(1), minValue: data.getColumnRange(1).min, maxValue: data.getColumnRange(1).max}, legend: 'none' }; 

Now we need to bind a chart to our <div> and tell the chart to draw the current view with the options we selected:

 var chart = new google.visualization.ScatterChart(document.getElementById('chart')); chart.draw(view, options); 

All that’s left for this stage is to close our function blocks:

 }); } 

If you load our current progress you should see the following (relatively meaningless) chart: Basic Chart

Adding Interaction

This chart already features interactivity in the form of rollover states for the plotted points. What we really need is to be able to change the variables we are plotting on the fly. Add the following tags after the </div> tag. I place the range first so that it lines up with the y-axis title:

 <select id="range"> </select> <select id="domain"> </select> <button type="button">Update Chart</button> 

Now we need to update our script to first load the <select> tags with the CSV headers, and also to respond to a click on our button.

Adding <options> to the <select> elements

Immediately following the assignment of arrayData, add the CSV headers to the <select> element:

 // use arrayData to load the select elements with the appropriate options for (var i = 0; i < arrayData[0].length; i++) { // this adds the given option to both select elements $("select").append("<option value='" + i + "'>" + arrayData[0][i] + "</option"); } 

Make sure the <select> elements show the starting options:

 // set the default selection $("#domain option[value='0']").attr("selected","selected"); $("#range option[value='1']").attr("selected","selected"); 

Updating the Chart

Now we need to assign a function to the button we created. Add the following after chart.draw(view, options);:

 // set listener for the update button $("button").click(function(){ 

Assign the selected column indices to local variables:

 // determine selected domain and range var domain = +$("#domain option:selected").val(); var range = +$("#range option:selected").val(); 

Update the view to reflect the selected columns:

 // update the view view.setColumns([domain,range]); 

Update the axis titles and the axis ranges:

 // update the options options.hAxis.title = data.getColumnLabel(domain); options.hAxis.minValue = data.getColumnRange(domain).min; options.hAxis.maxValue = data.getColumnRange(domain).max; options.vAxis.title = data.getColumnLabel(range); options.vAxis.minValue = data.getColumnRange(range).min; options.vAxis.maxValue = data.getColumnRange(range).max; 

Update the chart and close the function block:

 // update the chart chart.draw(view, options); }); 

Cool! Now we can do more interesting comparisons like plotting cm_16_exp and mean_educ. Here’s what our current chart looks like: Interactive Chart

Even Better UX

UX = User experience. User experience design is an important consideration. We want visitors to our site/blog to enjoy exploring our data. To make our chart more enjoyable, let’s remove the annoying step of having to click the button to update. Simply change this:

 $("button").click(function(){ 

to this:

 $("select").change(function(){ 

and remove the <button> tag. Now your chart should look like this (view the source and compare to yours if your chart is not working).

Conclusion

I hope you enjoyed this tutorial, and especially the end project. Now, to use your own CSV, all you need to do is change the file string “kzn1993.csv” to the name of your CSV and change the title in the chart options. In the next tutorial, we’ll use the Google visualization library to make a bubble chart. (Check out the third tutorial in this series: Google Charts and CSV Part 3: Side-by-Side Bubble Charts)As always, place any questions or comments in the section below. Thanks!