Creating interactive web graphs with R: Overview and googleVis tutorial

Markus Gesmann, RSS Conference 2012 , 5 September 2012

Hello - About me

Blog banner

Agenda

The perception of data is changing

The way we are consuming news and data is changing

No more boring data

Interactive charts have made data ‘sexy’

Motivation for googleVis

Introduction to Google Chart Tools

Motion chart example - Rendered output

Motion chart example - Code

Structure of Google Charts

The chart code has five generic parts:
  1. References to Google’s AJAX (l. 4) and Visualisation API (ll. 7 – 8),
  2. Data to visualise as a DataTable (ll. 11 – 24),
  3. Instance call to create the chart (ll. 25 – 26),
  4. Method call to draw the chart including options, shown here as width and height (l. 27),
  5. HTML <div> element to add the chart to the page (ll. 32 – 34).

How hard can it be?

  1. Transform data into JSON object
  2. Wrap some HTML and JavaScript around it

Thus, googleVis started life in August 2010

What is googleVis?

Video tutorial

googleVis version 0.2.17 provides interfaces to

Run demo(googleVis) to see examples of all charts and read the vignette for more details.

World Bank data demo

library(googleVis)
demo(WorldBank)

Key ideas of googleVis

(dat <- data.frame(x = LETTERS[1:2], y = 1:2))
##   x y
## 1 A 1
## 2 B 2
cat(toJSON(dat))
## {
##  "x": [ "A", "B" ],
## "y": [ 1, 2 ] 
## }

The googleVis concept

M <- gvisMotionChart(data, idvar='id', timevar='date', 
                     options=list(), chartid)

Simple line chart

df <- data.frame(label=c("A", "B", "C"), 
                 val1=c(1,3,4), 
                 val2=c(23,12,32))
lc <- gvisLineChart(df, chartid="line")
plot(lc)

gvis-Chart structure

List structure gvis object structure
names(lc)
## [1] "type"    "chartid" "html"   
lc$type
## [1] "LineChart"
lc$chartid
## [1] "line"
names(lc$html)
## [1] "header"  "chart"   "caption" "footer" 

gvis-Chart header

cat(lc$html$header)  ## same as print(lc, 'header')
## <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
##         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
## <html xmlns="http://www.w3.org/1999/xhtml">
## <head>
##   <title>line</title>
##   <meta http-equiv="content-type" content="text/html;charset=utf-8" />
##   <style type="text/css">
##     body {
##           color: #444444;
##           font-family: Arial,Helvetica,sans-serif;
##           font-size: 75%;
##     }
##     a {
##           color: #4D87C7;
##           text-decoration: none;
##     }
##   </style>
## </head>
## <body>

gvis-Chart chart

names(lc$html$chart)
## [1] "jsHeader"       "jsData"         "jsDrawChart"    "jsDisplayChart"
## [5] "jsChart"        "jsFooter"       "divChart"      

gvis-Chart

print(lc, "jsHeader")
## <!-- LineChart generated in R 2.15.1 by googleVis 0.2.17 package -->
## <!-- Tue Sep 11 19:01:27 2012 -->
## 
## 
## <!-- jsHeader -->
## <script type="text/javascript" src="http://www.google.com/jsapi">
## </script>
## <script type="text/javascript">

gvis-Chart

print(lc, "jsData")
## 
## // jsData 
## function gvisDataline ()
## {
##   var data = new google.visualization.DataTable();
##   var datajson =
## [
##  [
##  "A",
##           1,
##          23 
## ],
## [
##  "B",
##           3,
##          12 
## ],
## [
##  "C",
##           4,
##          32 
## ] 
## ];
## data.addColumn('string','label');
## data.addColumn('number','val1');
## data.addColumn('number','val2');
## data.addRows(datajson);
## return(data);
## }

gvis-Chart

print(lc, "jsDrawChart")
## 
## // jsDrawChart
## function drawChartline() {
##   var data = gvisDataline();
##   var options = {};
## options["allowHtml"] = true;
## 
##      var chart = new google.visualization.LineChart(
##        document.getElementById('line')
##      );
##      chart.draw(data,options);
##     
## 
## }
##   

gvis-Chart

print(lc, "jsDisplayChart")
## 
## // jsDisplayChart 
## function displayChartline()
## {
##   google.load("visualization", "1", { packages:["corechart"] }); 
##   google.setOnLoadCallback(drawChartline);
## }

gvis-Chart

print(lc, "jsChart")
## 
## // jsChart 
## displayChartline()

gvis-Chart

print(lc, "jsFooter")
## 
## <!-- jsFooter -->  
## //-->
## </script>

gvis-Chart

print(lc, "divChart")
## 
## <!-- divChart -->
##   
## <div id="line"
##   style="width: 600px; height: 500px;">
## </div>

gvis-Chart

print(lc, "caption")
## <div><span>Data: data &#8226; Chart ID: <a href="Chart_line.html">line</a></span><br />

gvis-Chart

print(lc, "footer")
## 
## <!-- htmlFooter -->
## <span> 
## R version 2.15.1 (2012-06-22) &#8226; <a href="http://code.google.com/p/google-motion-charts-with-r/">googleVis-0.2.17</a>
## &#8226; <a href="https://developers.google.com/terms/">Google Terms of Use</a> &#8226; <a href="https://google-developers.appspot.com/chart/interactive/docs/gallery/linechart.html#Data_Policy">Data Policy</a>
## </span></div>
## </body>
## </html>

Line chart with options set

print(gvisLineChart(df, xvar="label", yvar=c("val1","val2"),
        options=list(title="Hello World", legend="bottom",
                titleTextStyle="{color:'red', fontSize:18}",                         
                vAxis="{gridlines:{color:'red', count:3}}",
                hAxis="{title:'My Label', titleTextStyle:{color:'blue'}}",
                series="[{color:'green', targetAxisIndex: 0}, 
                         {color: 'blue',targetAxisIndex:1}]",
                vAxes="[{title:'Value 1 (%)', format:'#,###%'}, 
                                  {title:'Value 2 (\U00A3)'}]",                          
                curveType="function", width=500, height=300                         
                )), 'chart')

On-line changes

You can enable the chart editor which allows users to change the chart.

print(gvisLineChart(df, 
      options=list(gvis.editor="Edit me!")),
      'chart')

Change motion chart settings

print(gvisMotionChart(Fruits, "Fruit", "Year"), "chart")

Can change displaying settings via the browser. The state string from the ‘Advanced’ tab can be used to set those settings via R.

Motion chart with initial settings changed

myStateSettings <- '
{"xZoomedDataMin":1199145600000,"colorOption":"2",
 "xZoomedDataMax":1262304000000,"iconType":"LINE",
 "dimensions":{"iconDimensions":["dim0"]},
 "xAxisOption":"_TIME","orderedByX":false,"playDuration":15000,
 "xZoomedIn":false,"time":"2010","yZoomedDataMin":0,
 "yZoomedIn":false,"orderedByY":false,"yZoomedDataMax":100}
'
print(gvisMotionChart(Fruits, "Fruit", "Year", 
      options=list(state=myStateSettings, height=300)), 'chart')

Displaying geographical information

Plot countries’ S&P credit rating sourced from Wikipedia

## Get and prepare data
library(XML)
url <- "http://en.wikipedia.org/wiki/List_of_countries_by_credit_rating"
page <- readLines(url)
x <- readHTMLTable(page, which=3)
levels(x$Rating) <- substring(levels(x$Rating), 4, 
                            nchar(levels(x$Rating)))
x$Ranking <- x$Rating
levels(x$Ranking) <- nlevels(x$Rating):1
x$Ranking <- as.character(x$Ranking)
x$Rating <- paste(x$Country, x$Rating, sep=": ")

## Create a geo map
G <- gvisGeoMap(x, "Country", "Ranking", "Rating",
                options=list(gvis.editor="S&P", 
                             colors="[0x91BFDB, 0XFC8D59]", 
                             gvis.editor="Edit me"))

Chart countries’ S&P credit rating

print(G, "chart")

Geo chart with markers

Display earth quake information of last 30 days

library(XML)
eq <- readHTMLTable(readLines("http://www.iris.edu/seismon/last30.html"),
 colClasses=c("factor", rep("numeric", 4), "factor"), which=2)
eq$loc=paste(eq$LAT, eq$LON, sep=":")
G <- gvisGeoChart(eq, "loc", "DEPTH km", "MAG",
                   options=list(displayMode="Markers", 
                   colorAxis="{colors:['purple', 'red', 'orange', 'grey']}",
                   backgroundColor="lightblue"), chartid="EQ")
print(G, 'chart')

Org chart

Org <- gvisOrgChart(Regions, options=list(width=600, height=250,
                               size='large', allowCollapse=TRUE))
print(Org, 'chart')

Org chart data

Regions
##     Region  Parent Val Fac
## 1   Global    <NA>  10   2
## 2  America  Global   2   4
## 3   Europe  Global  99  11
## 4     Asia  Global  10   8
## 5   France  Europe  71   2
## 6   Sweden  Europe  89   3
## 7  Germany  Europe  58  10
## 8   Mexico America   2   9
## 9      USA America  38  11
## 10   China    Asia   5   1
## 11   Japan    Asia  48  11

Notice the data structure. Each row in the data table describes one node. Each node (except the root node) has one or more parent nodes.

Tree map

Same data structure as for org charts required.

Tree <- gvisTreeMap(Regions,  idvar="Region", parentvar="Parent",
                    sizevar="Val", colorvar="Fac",
                    options=list(width=500, height=350))
print(Tree, 'chart')

Annotated time line data

Stock
##          Date  Device  Value          Title                  Annotation
## 1  2008-01-01 Pencils   3000           <NA>                        <NA>
## 2  2008-01-02 Pencils  14045           <NA>                        <NA>
## 3  2008-01-03 Pencils   5502           <NA>                        <NA>
## 4  2008-01-04 Pencils  75284           <NA>                        <NA>
## 5  2008-01-05 Pencils  41476 Bought pencils         Bought 200k pencils
## 6  2008-01-06 Pencils 333222           <NA>                        <NA>
## 7  2008-01-01    Pens  40645           <NA>                        <NA>
## 8  2008-01-02    Pens  20374           <NA>                        <NA>
## 9  2008-01-03    Pens  50766           <NA>                        <NA>
## 10 2008-01-04    Pens  14334   Out of stock Ran of stock on pens at 4pm
## 11 2008-01-05    Pens  66467           <NA>                        <NA>
## 12 2008-01-06    Pens  39463           <NA>                        <NA>

Annotated time line

A1 <- gvisAnnotatedTimeLine(Stock, datevar="Date",
                           numvar="Value", idvar="Device",
                           titlevar="Title", annotationvar="Annotation",
                           options=list(displayAnnotations=TRUE,
                            legendPosition='newRow',
                            width=600, height=350)
                           )
print(A1, 'chart')

Merging gvis-objects

G <- gvisGeoChart(Exports, "Country", "Profit", 
                  options=list(width=250, height=120))
B <- gvisBarChart(Exports[,1:2], yvar="Profit", xvar="Country",                  
                  options=list(width=250, height=260, legend='none'))
M <- gvisMotionChart(Fruits, "Fruit", "Year",
                     options=list(width=400, height=380))
GBM <- gvisMerge(gvisMerge(G,B, horizontal=FALSE), 
                 M, horizontal=TRUE, tableOptions="cellspacing=5")
print(GBM, 'chart')

Embedding googleVis chart into your web page

Suppose you have an existing web page and would like to integrate the output of a googleVis function, such as gvisMotionChart.

In this case you only need the chart output from gvisMotionChart. So you can either copy and paste the output from the R console

print(M, "chart")  ## or cat(M$html$chart)

into your existing html page, or write the content directly into a file

print(M, "chart", file = "myfilename")

and process it from there.

Embedding googleVis output via iframe

  1. Host the googleVis output on-line, e.g. public Dropbox folder
  2. Use the iframe tag on your page:

Building applications with googleVis and Rook

googleVis with Rook

googleVis with Rook

Screen shot of Rook window

For more details see my blog post.

Further case studies

Other R packages

How I created this presentation with RStudio, knitr, pandoc and slidy

Rscript -e "library(knitr); knit('googleVis_at_RSS_2012.Rmd')"
pandoc -s -S -i -t slidy --mathjax googleVis_at_RSS_2012.md 
  -o googleVis_at_RSS_2012.html

Conclusions

Contact

Thanks

Questions?