Category Archives: R and the web

Comparing Shiny with gWidgetsWWW2.rapache

(A guest post by John Verzani)

A few days back the RStudio blog announced Shiny, a new product for easily creating interactive web applications (http://www.rstudio.com/shiny/). I wanted to compare this new framework to one I’ve worked on, gWidgetsWWW2.rapache – a version of the gWidgets API for use with Jeffrey Horner’s rapache module for the Apache web server (available at GitHub). The gWidgets API has a similar aim to make it easy for R users to create interactive applications.

I don’t want to worry here about deployment of apps, just the writing side. The shiny package uses websockets to transfer data back and forth from browser to server. Though this may cause issues with wider deployment, the industrious RStudio folks have a hosting program in beta for internet-wide deployment. For local deployment, no problems as far as I know – as long as you avoid older versions of internet explorer.

Now, Shiny seems well suited for applications where the user can parameterize a resulting graphic, so that was the point of comparison. Peter Dalgaard’s tcltk package ships with a classic demo tkdensity.R. I use that for inspiration below. That GUI allows the user a few selections to modify a density plot of a random sample.

gWidgetsWWW2

We’ll start with a gWidgets approach and work our way to the shiny code. A basic GUI can be generated with the following code:

?View Code RSPLUS
 
width <- 600; height <- 480
 
## The plot commands. Uses GUI objects defined below
make_plot <- function(...) {
  y <- get(svalue(distribution))(svalue(size))
  plot(density(y, bw=svalue(bandwidth)/100, kernel=svalue(kernel)))
  points(y, rep(0, svalue(size) ))
}
 
update_plot <- function(...) {
  f <- tempfile()
  require(canvas)
  canvas(f, width=width, height=height)
  make_plot()
  dev.off()
  svalue(cnv) <- f ## update canvas widget
}
 
## The layout
w <- gwindow("tkdensity example")
gstatusbar("Powered by gWidgetsWWW2.rapache and rapache", cont=w)
 
## containers
bl <- gborderlayout(cont=w)
fl <- gformlayout(cont=bl, where="west")
 
## controls
distribution <- gcombobox(data.frame(value=c("rnorm", "rexp"),
                                     labels=c("Normal", "Exponential"),
                                     stringsAsFactors=FALSE),
                          cont=fl, label="distribution")
kernel <- gcombobox(c("gaussian", "epanechnikov", "rectangular",
             "triangular", "cosine"),
                    cont=fl, label="kernel")
size <- gcombobox(c(5,50, 100, 200, 300),
                  coerce.with="as.numeric",
                  cont=fl, label="size")
bandwidth <- gslider(0.05*100, 2*100, by=0.05*100, value=1*100,
                     width=250,
                     coerce.with="as.numeric",
                     cont=fl, label="bandwidth")
refresh <- gbutton("refresh",
                   cont=fl, label="")
 
cnv <- gcanvas(cont=bl, where="center", width=width, height=height)
 
## connect controls
for(i in list(kernel, size, bandwidth, refresh))
  addHandlerChanged(i, update_plot)

All right, that may look like a lot, but lots of people have used gWidgets to write such GUIs. They aren’t that hard. basically there are three parts:

  • The definition of the controls and their layout that comprise the
    user interface.
  • The definition of some callback to create the graphic when a control
    is updated.
  • Some means to specify when to invoke this call back.

The gWidgets API is meant to be cross-toolkit, but this is only mostly true. In the above we use a few web-specific features, including the canvas package to provide a JavaScript canvas for drawing R graphics.

Manipulate

This particular example would be really easy were we able to use RStudio’s manipulate package. That is only for RStudio users though. Well, not really. There is a simple map available in the gWidgetsWWW2.rapache package that allows us to easily use that specification. Here is the code:

?View Code RSPLUS
 
## load in map for manipulate -> gWidgets
source(system.file("demo", "manipulate.R", package="gWidgetsWWW2.rapache"), local=TRUE)
 
w <- gwindow("Manipulate example")
gstatusbar("Powered by gWidgetsWWW2.rapache and rapache", cont=w)
 
manipulate(
           {
             y <- get(distribution)(size)
             plot(density(y, bw=bandwidth/100, kernel=kernel))
             points(y, rep(0, size))
           },
           ##
           distribution=picker("Normal"="rnorm", "Exponential"="rexp"),
           kernel=picker("gaussian", "epanechnikov", "rectangular",
             "triangular", "cosine"),
           size=picker(5, 50, 100, 200, 300),
           bandwidth=slider(0.05 * 100, 2.00 * 100, step=0.05 * 100, initial=1* 100), # integers needed
           button=button("Refresh"),
           ## gWidgetsWWW2.rapache extras
           container=w,       
           device="svg",                # svg or canvas or png
           delay=1000                   # delay to let data load for combo boxes
           )

Okay, I admit. I’m a fan of manipulate and it really is a perfect way to specify an interface as straightforward as this. This one is an example in the gWidgetsWWW2.rapache package and you can see it in action at http://www.math.csi.cuny.edu/gw/ex-manipulate.R (though this redirects to a private server which is often not online). The manipulate interface handles the layout of the controls and the invocation of the callback, all you add is an expression to plot and a specification of
the controls.

Shiny

Now for Shiny. We noted above there are really three pieces to writing this app, with Shiny we only need to worry about two: the definition and layout of the user interface, and the specification of how the resulting graphic is made. For this, we write two functions: ui.R and server.R.

The ui.R files is used to layout the interface. Here is ours:

?View Code RSPLUS
library(shiny)
 
shinyUI(pageWithSidebar(
 
  # Application title
  headerPanel("tkdensity"),
 
  # Sidebar with a slider input for number of observations
  sidebarPanel(
               selectInput("distribution", "Distribution:", 
                           choices = c("Normal"="rnorm", "Exponential"="rexp")),
               selectInput("kernel", "Kernel:", 
                           choices = c("gaussian", "epanechnikov", "rectangular",
                             "triangular", "cosine")),
               selectInput("size", "Size:", 
                           choices = c(5,50, 100, 200, 300)),
               sliderInput("bandwidth", "bandwidth:", 
                           min = 0.05, 
                           max = 2, 
                           value = 1)
  ),
 
  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))

There are a few containers (“panels”) and a few controls specified (“inputs”). The basic usage of shiny involves just a handful of each and they are easy to learn. The above code simply makes a header, puts four controls into a side panel and in the main panel readies a place to display our plots. The name distPlot is odd because I stole this basic set up from one of shiny‘s examples and made just minor changes.

The server.R file is not difficult either. We need to make the graphic so that it displays. Here it is:

?View Code RSPLUS
library(shiny)
 
shinyServer(function(input, output) {
 
  make_plot <- function(distribution, size, bandwidth, kernel) {
    y <- get(distribution)(size)
    plot(density(y, bw=bandwidth, kernel=kernel))
    points(y, rep(0, size))
  }
 
  output$distPlot <- reactivePlot(function() {
    make_plot(input$distribution, input$size, input$bandwidth, input$kernel)
  })
})

Again, this is only slightly modified from an example. The input object is not a list or an environment, but we can extract the values associated with the user interface as though it were. In the above we see the distributionsizebandwidth and kernel values are passed along to the make_plot call. The only new thing here, besides that, is the magic way we create a plot (passing a function as a call back to reactivePlot and assigning it to distPlot in the output object). The shiny package takes care of the third part of our GUI, using this “reactive” programming style to synchronize various parts of
the interface.

Want to see it at work? Well fire up your copy of shiny and run it from a GitHub gist:

?View Code RSPLUS
require(shiny)
shiny:::runGist("4009017")

Before you gloss over the above lines, think how neat this is. Just as you can install packages from GitHub within an R session through the devtools package, you can run shiny apps within R from GitHub with the runGist function. This is an awesome feature for deploying interactive web apps for local usage.

I think you’ll see, if you compare, for this task the user experience is nicer with shiny than that of gWidgetsWWW2.rapache. The specification of the GUI is easiest with the manipulate style, but using shiny wasn’t difficult. I personally like very much the use of the “bootstrap” CSS libraries (http://twitter.github.com/bootstrap/), as opposed to the ExtJS CSS (http://www.sencha.com/products/extjs/). The interface looks very modern. (Not only looks, the slider is much better than that in gWidgetsWWW2.rapache, where the underlying control only wants integer values.) Though the gWidgetsWWW2.rapache package might have more controls and more layout options than the basic use of shiny, I can see that there will be a huge number of great shiny apps written. Within its range of use, it is a great choice for easily making R-driven web applications.

About:

John Verzani is the maintainer of the gWidgets set of packages and co-author with Michael Lawrence of the book Programming Graphical User Interfaces in R.

“The next big thing”, R, and Statistics in the cloud

A friend just e-mailed me about a blog post by Dr. AnnMaria De Mars titled “The Next Big Thing”.

In it Dr. De Mars wrote (I allowed myself to emphasize some parts of the text):

Contrary to what some people seem to think, R is definitely not the next big thing, either. I am always surprised when people ask me why I think that, because to my mind it is obvious. [...]
for me personally and for most users, both individual and organizational, the much greater cost of software is the time it takes to install it, maintain it, learn it and document it. On that, R is an epic fail. It does NOT fit with the way the vast majority of people in the world use computers. The vast majority of people are NOT programmers. They are used to looking at things and clicking on things.

Here are my two cents on the subject:
Read more »

Jeroen Ooms’s ggplot2 web interface – a new version released (V0.2)

Good news.

Jeroen Ooms released a new version of his (amazing) online ggplot2 web interface:

yeroon.net/ggplot2 is a web interface for Hadley Wickham’s R package ggplot2. It is used as a tool for rapid prototyping, exploratory graphical analysis and education of statistics and R. The interface is written completely in javascript, therefore there is no need to install anything on the client side: a standard browser will do.

The new version has a lot of cool new features, like advanced data import, integration with Google docs, converting variables from numeric to factor to dates and vice versa, and a lot of new geom’s. Some of which you can watch in his new video demo of the application:

The application is on:
http://www.yeroon.net/ggplot2/

p.s: other posts about this (including videos explaining how some of this was done) can be views on the category page: R and the web

R Web Application – “Hello World” using RApache (~7min video tutorial)

I just noticed a google buzz from Jeroen ooms, with a Youtube video titled “RApache Hello World + POST arguments + catching errors.

In this ~7 min video tutorial, Jeroen shares with us:

  1. How to write ”Hello World” in a website using RApache.
  2. How to extract arguments from a form submited by the website visitor (and then inserting it into an “rnorm” function so to control the output). And finally,
  3. How to catch an error in case of an invalid argument on an R Web Application.

Thank you Jeroen for a very simple, step by step, tutorial:

p.s: For more videos by Jeroen, have a look at

Web Development with R – an HD video tutorial of Jeroen Ooms talk

Here is a HD version of a video tutorial on web development with R, a lecture that was given by Jeroen Ooms (the guy who made A web application for R’s ggplot2). This talk was given at the Bay Area UseR Group meeting on R-Powered Web Apps.

You can also view the slides for his talk and view (great) examples for: stockplotlme4, and gpplot2.

Thanks again to Jeroen for sharing his knowledge and experience!

A web application for R’s ggplot2

One of the exciting new frontiers for R programming is of creating website interfaces to R code. At the forefront of this domain is a young and (very) bright man called Jeroen Ooms, whom I had the pleasure of meeting at useR 2009 (press the link to see his presentation).

Today Jeroen announced a new version (0.11) of his web interface to ggplot2. See it here:
http://www.yeroon.net/ggplot2/

As Jeroen wrote:

New features include 1D geom’s (histogram, density, freqpoly), syntax mode (by clicking the tiny arrow at the bottom), and some additional facet options. And some minor improvements and fixes, most notably for Internet Explorer.
The data upload has not been improved yet, I am working on that. For now, it supports .csv, .sav (spss), and tab delimited data. Please make sure your filename has the appropriate extension and every column has a header in your data. If you export a dataframe from R, use:
write.csv(mydf, ”mydf.csv” , row.names=F). If you upload an spss
datafile, none of this should be a concern.
Supported browsers are IE6-8, FF, Safari, and Chrome, but a recent browser is highly recommended. As always, feedback is more than welcome.

Here is a little demo video that shows how to use the new features:

The datafile from the demo is available at http://www.yeroon.net/ggplot2/myMovies.csv.

I wish the best to Jeroen, and hope to see many more such uses in the future.