Google Chart Tools

Riccardo Govoni
June 29, 2011

Who am I?

Steam powered coder @ Google since 2007.

Focusing on data visualizations for Google Chart Tools, Google AdSense and others.

Generally a fan of visualizations, data mining, html5 and latest browser technologies.

Mail: battlehorse@google.com
Twitter: @battlehorse
Home: battlehorse.net

Agenda

"Google Chart Tools" is...

Principles

Simple

Flexible

Powerful

3 Tiers

Charts

Data

Providers

Simple and Ready to use

Simple: Spreadsheets

New Chart Editor in Google Spreadsheets Demo

Simple: Spreadsheets (cont'd)

Spreadsheet

Simple: Fusion Tables - Demo

What is Google Apps Script?

"A JavaScript cloud scripting language that provides easy ways to automate tasks across Google products and third party services."

Built-in support for charts in Google Apps Script

Demo

Apps Script demo

function createChartAndSendEmail() {
  var dt = Charts.newDataTable().
    addColumn(Charts.ColumnType.STRING, "IceCream").
    addColumn(Charts.ColumnType.NUMBER, "Number Eaten");

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
  var values = sheet.getRange("A1:B20").getValues();
  for (var r = 0; r < values.length; r++) {
    dt.addRow(values[r]);
  }
  
  var chart = Charts.newPieChart().
      setDataTable(dt).
      set3D().
      setTitle("My Chart!").
      build();
  var chartBlob = chart.getBlob().getBytes();
  
  var mailBody = "Here is your chart!";
  
  // Send as mail attachment
  var chartFile = [{fileName:"chart.png", content:chartBlob, mimeType: "image/png"}];
  MailApp.sendEmail( "battlehorse@google.com", "Your Chart!", 
    mailBody, {attachments: chartFile});
}

Features

3 Tiers

Charts

Data

Providers

Chart Features

Customizable

Charts are Flexible

Charts are Flexible

Gravity Wells

Charts are Flexible

Charts are Flexible

Scatterplots are awesome!

Simple API

HTML Skeleton

The very minimum you need to use the Chart Tools API

<html>
  <head>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('visualization', '1');
      google.setOnLoadCallback(drawChart);
      function drawChart() {

        // your code here.

      });
    </script>
  </head>
  <body>
  </body>
</html>

ChartWrapper

Single key that opens all chart doors.

function drawChart() {

  new google.visualization.ChartWrapper({
    'dataSourceUrl': 'http://spreadsheets.google.com/tq?key=abc',
    'chartType': 'PieChart'
  }).draw(document.getElementById('container'));

}

Demo

ChartWrapper is: Customizable

ChartWrapper is: Smart

Let the user Customize your charts too!

You have seen the editor in Google Spreadsheets. Now open to the world: google.visualization.ChartEditor

Chart Editor - Code

// Create the ChartWrappter.
var chartWrapper = new google.visualization.ChartWrapper({
  dataSourceUrl: url    // Using a remote data source.
});

// Create an editor instance.
var editor = new google.visualization.ChartEditor();

// Listen to the 'ok' button/event.
google.visualization.events.addListener(editor, 'ok', function() {
       editor.getChartWrapper().draw(chartContainer);
    });

// Open the editor's dialog.
editor.openDialog(chartWrapper);

3 Tiers

Charts

Data

Providers

DataTable

Great for interoperability!

DataTable

var data2 = new google.visualization.arrayToDataTable([
  ['Country', 'Population', 'Area'],
  ['CN', 1324, 9640821],
  ['IN', 1133, 3287263],
  ['US', 304, 9629091],
  ['ID', 232, 1904569],
  ['BR', 187, 8514877]
]);
var data = new google.visualization.DataTable();
data.addColumn('string','Country');
// ...
data.addRows(5);
data.setValue(0, 0, 'CN');
// ...
var json = {cols: [/*...*/], rows: [/*...*/]};
var data = new google.visualization.DataTable(json);

DataSources

Two tiers

DataSource API

Custom datasource

import gviz_api

def main():
  # Creating the data
  description = {"name": ("string", "Name"),
                 "salary": ("number", "Salary"),
                 "full_time": ("boolean", "Full Time Employee")}
  data = [{"name": "Mike", "salary": (10000, "$10,000"), "full_time": True},
          {"name": "Jim", "salary": (800, "$800"), "full_time": False},
          ...]

  # Loading it into gviz_api.DataTable
  data_table = gviz_api.DataTable(description)
  data_table.LoadData(data)

  # Creating a JSon string
  json = data_table.ToJSon(
    columns_order=("name", "salary", "full_time"),
    order_by="salary")

Libraries for Python, Java, including query tokenization.
Open wire protocol to parse data requests.

Comparison

What are the alternatives?

Advanced: Roll your own

Advanced: Extension API

Create your own visualizations. Leverage the existing framework.

myVisualization = function(container) {
  this.container_ = container;
};

myVisualization.prototype.draw = function(dataTable, options) {
  // your code here.
};

new google.visualization.ChartWrapper({
  'chartType': 'myVisualization',
  'dataTable': data,
  'options': {'legend': 'right'},
  'containerId': 'chartContainerElement'}).draw();
Demo

Advanced: Dashboards

Visualizations are helpful

but they offer a single perspective.

Wiring is hard

when you want multiple visualizations to play together

Controls gallery

Google Analytics dashboard screenshot

Dashboard

A collection of collaborating controls and visualizations, sharing the same underlying data.

Demo

Xkcd vs Dilbert

How do Controls and Dashboard work?











  new google.visualization.ChartWrapper({
    'chartType': 'PieChart',
    'options': {'legend': 'right'},
    'containerId': 'chartContainerElement'})
           
                  


  new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'filterColumnLabel': 'Salary',
    'options': {'minValue': 10, 'maxValue': 100},
    'containerId': 'controlContainerElement'})



  new google.visualization.ChartWrapper({
    'chartType': 'PieChart',
    'options': {'legend': 'right'},
    'containerId': 'chartContainerElement'})

                 
new google.visualization.Dashboard(dashboardElement).bind([

  new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'filterColumnLabel': 'Salary',
    'options': {'minValue': 10, 'maxValue': 100},
    'containerId': 'controlContainerElement'})

],[

  new google.visualization.ChartWrapper({
    'chartType': 'PieChart',
    'options': {'legend': 'right'},
    'containerId': 'chartContainerElement'})

])
new google.visualization.Dashboard(dashboardElement).bind([

  new google.visualization.ControlWrapper({
    'controlType': 'NumberRangeFilter',
    'filterColumnLabel': 'Salary',
    'options': {'minValue': 10, 'maxValue': 100},
    'containerId': 'controlContainerElement'})

],[

  new google.visualization.ChartWrapper({
    'chartType': 'PieChart',
    'options': {'legend': 'right'},
    'containerId': 'chartContainerElement'})

]).draw(dataTable);

google.visualization.ChartWrapper

Simple wrapper around all chart types. Dead simple.

var wrapper = new google.visualization.ChartWrapper({
  'chartType': 'GeoChart',
  'dataTable': myData,
  'containerId': 'geoElementId',
  'options': {}
});
wrapper.draw();

// Change colors and redraw.
wrapper.setOption('colors', [ '#D6F1FF', '#0A43BF' ]);
wrapper.draw();

// Serialize to JSON
var json = wrapper.toJSON();

google.visualization.ControlWrapper

UI element that collects user input and drives visualizations.

var wrapper = new google.visualization.ControlWrapper({
  'controlType': 'NumberRangeFilter',
  'containerId': 'controlElementId',
  'options': {
    'filterColumnLabel': 'salary',
    'minValue': 100,
    'maxValue': 1000
    },
  'state': {'lowValue': 200, 'highValue': 600}
});

// Change the Control state programmatically
wrapper.setState({'lowValue': 400, 'highValue': 800});

wrapper.setOption('minValue', 0); // And the options too..

google.visualization.Dashboard

Takes care of all the plumbing so you don't have to.

var dashboard = new google.visualization.Dashboard(
  document.getElementById('container'));

// Have one or more Controls affect one or more Charts.
dashboard.bind(
  [controlWrapper1, controlWrapper2],
  [chartWrapper1, chartWrapper2, chartWrapper3]);

// Controls can also affect each other.
dashboard.bind(controlWrapper1, controlWrapper2);

// Draw the entire dashboard.
dashboard.draw(dataTable);

Thanks!