August 10th, 2015

on the Web

Why interactive graphics on the Web?

  1. Portable (web browser)
  2. Simple (share via URL)
  3. Reach (everyone has internet, right?)

Figure converters

library(animint)
p <- qplot(data = iris, x = Sepal.Width, y = Sepal.Length, color = Species)
structure(list(p = p), class = "animint")

library(plotly)
ggplotly(p)

library(gridSVG)
gridsvg("iris.svg")
  p
dev.off()

<html>
  <head>
    <script type="text/javascript" src="animint.js"></script>
  </head>
  <body>
    <div id="plot" align="center"> </div>
    <script>
      var plot = new animint("#plot","plot.json");
    </script>
  </body>
</html>

How do we test the renderer?

  • RSelenium allows you to program any modern Web browser from R.
    library(RSelenium)
    startServer()
    remDr <- remoteDriver(browserName = "firefox")
    remDr$open()
    remDr$navigate("http://www.r-project.org")
    # returns the DOM as HTML
    src <- remDr$getPageSource()
  • Can also do fancier stuff like handle user events (mouse clicks, press keys, etc.)
  • If you just need to access the DOM, rdom is easier and more reliable.
    src <- rdom::rdom("http://www.r-project.org")

Thoughts on figure converters

  • Pros:
    • Users don't need HTML/JS/CSS knowledge
    • Doesn't require a Web Server running special software
    • Easy to use – extrapolates on existing knowledge/code
  • Cons:
    • Serialization depends on internals of other packages
    • To change something that's serialized, you need to re-run R code
    • Hard to extend, customize, and/or add (interactive) features

R Bindings to JavaScript Libraries

  • General idea:
    • Start with a HTML/JS/CSS template
    • Abstract away data and layout/appearance options
    • Map a set of R objects to template
    myWrapper <- function(...) {
      # compute stuff
      toJSON(list(...))
    }
  • htmlwidgets makes it easy to write bindings that play nicely with shiny/rmarkdown/RStudio.

(p <- plot_ly(z = volcano, type = "surface"))

str(p)
#> Classes ‘plotly’ and 'data.frame':   0 obs. of  0 variables
#>  - attr(*, "plotly_hash")= chr "d72417c2f38125f11112cd6591f06f2e#2"

str(plotly_build(p))
#> List of 4
#>  $ data          :List of 1
#>   ..$ :List of 3
#>   .. ..$ type      : chr "surface"
#>   .. ..$ z         : num [1:87, 1:61] 100 101 102 103 104 105 105 106 107 108 ...
#>   .. ..$ colorscale:'data.frame':    10 obs. of  2 variables:
#>   .. .. ..$ : num [1:10] 0 0.111 0.222 0.333 0.444 ...
#>   .. .. ..$ : Factor w/ 10 levels "#1F9D89","#26838E",..: 6 7 5 3 2 1 4 8 9 10
#>  $ layout        :List of 1
#>   ..$ zaxis:List of 1
#>   .. ..$ title: chr "volcano"

plot_ly(economics, x = date, y = uempmed, mode = "markers") %>%
  add_trace(y = fitted(forecast::Arima(uempmed, c(1,0,0))), mode = "lines") %>%
  dplyr::filter(uempmed == max(uempmed)) %>%
  layout(annotations = list(x = date, y = uempmed, text = "Peak", showarrow = T),
         title = "Median duration of unemployment (in weeks)", showlegend = F)

Thoughts on JavaScript bindings

  • Defaults/abstractions matter!
    • Best when used to attack a specific problem/task
  • Pros:
    • Users don't need HTML/JS/CSS knowledge
    • Package authors can easily bring the best of JavaScript to R
  • Cons:
    • JavaScript developers don't think like statisticians
    • How do you abstract away reactivity/interactivity???

Final Thoughts

  • Web-based interactive statistical graphics are not (yet) as fully featured as non Web-based options (see LISP-STAT, cranvas, ggobi, loon, MANET, DataDesk, etc.)
  • Plea to developers:
    • build tools for domain specific problems (see qtlcharts, LDAvis)
    • focus less on features, more on what your audience really needs

Thanks for listening!