Plots for the web
There has been increasing need and desirability to produce interactive graphics online. News outlets, like the The Economist, New York Times, Vox, 538, Pew, and Quartz, routinely use interactive displays.
There are two packages (among several) that allow us to create interactive graphics.  The first is ggivis, which is based on ggplot2 and the other is googlevis.
ggvis follows the similar underlying theory of the grammar of graphics as ggplot2 but is expressed a little bit differently.  It incorporates aspects from shiny as well as dplyr.
ggvis()
NOTE:  For some reason my ggvis figures are not rendering and I am not 100% sure why.  If you follow along with the below R code in RStudio these will generate.  Hopefully, I can figure out what the issues are and I will update the post.
#install.packages("ggvis")
library(tidyverse)
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag():    dplyr, stats
library(ggvis)
## 
## Attaching package: 'ggvis'
## The following object is masked from 'package:ggplot2':
## 
##     resolution
Like ggplot(), every call to ggvis starts with the ggvis() statement.
point_plot<-mtcars %>%
            ggvis(x = ~wt, y = ~mpg) %>%
            layer_points()
view_static(point_plot)
Like ggplot, you can mapping other visual properties like fill, stroke, size and shape.
mtcars %>% ggvis(~mpg, ~disp, stroke = ~vs) %>% layer_points()
mtcars %>% ggvis(~mpg, ~disp, fill = ~vs) %>% layer_points()
mtcars %>% ggvis(~mpg, ~disp, size = ~vs) %>% layer_points()
mtcars %>% ggvis(~mpg, ~disp, shape = ~factor(cyl)) %>% layer_points()
Unlike ggplot, you specify points a fixed colour or size, you need to use := instead of =. The := operator means to use a raw, unscaled value.
mtcars %>% ggvis(~wt, ~mpg, fill := "black", stroke := "firebrick") %>% layer_points()
mtcars %>% ggvis(~wt, ~mpg, size := 400, opacity := 0.25) %>% layer_points()
mtcars %>% ggvis(~wt, ~mpg, size := 100, shape := "square") %>% layer_points()
Layers
- Points, layer_points(), with propertiesx,y,shape,stroke,fill,strokeOpacity,fillOpacity, andopacity.
mtcars %>% ggvis(~wt, ~mpg) %>% layer_points()
- Paths and polygons, layer_paths()
set.seed(12345)
df <- data.frame(x = 1:20, y = runif(20))
df %>% ggvis(~x, ~y) %>% layer_paths()
If you add fill, you will get a polygon.
vals<-rbind(data.frame(x = 1:10, y = 1),
      data.frame(x = 1:10, y = 3),
      data.frame(x = 1, y = 1:3),
      data.frame(x = 10, y = 1:3))
vals %>% ggvis(~x, ~y) %>% layer_paths(fill := "pink")
- Filled areas, layer_ribbons(). Use propertiesyandy2to control the extent of the area.
df %>% ggvis(~x, ~y) %>% layer_ribbons(fill:="green", opacity:=0.3)
df %>% ggvis(~x, ~y + 0.25, y2 = ~y - 0.25) %>% layer_ribbons(fill:="green", opacity:=0.3)
- Rectangles, layer_rects(). The location and size of the rectangle is controlled by thex,x2,yandy2properties.
set.seed(12345)
df <- data.frame(x1 = runif(2), x2 = runif(2), y1 = runif(2), y2 = runif(2))
df %>% ggvis(~x1, ~y1, x2 = ~x2, y2 = ~y2, fillOpacity := 0.55, fill:= "blue") %>% layer_rects()
- Text, layer_text(). Many options to control the apperance of the text:text(the label),dxanddy(margin in pixels between text and anchor point),angle(rotate the text),font(font name),fontSize(size in pixels),fontWeight(bold or normal), andfontStyle(e.g. italic or normal)
df2 <- data.frame(x = 4:1, y = c(1, 3, 2,4), label = c("a", "b", "c", "d"))
df2 %>% ggvis(~x, ~y, text := ~label) %>% layer_text()
df2 %>% ggvis(~x, ~y, text := ~label) %>% layer_text(fontSize := 50, fontWeight:= "bold", angle:= 45)
Compound layers
- layer_lines()automatically orders by the x variable:
t <- seq(0, 2 * pi, length = 20)
df3 <- data.frame(x = sin(t), y = cos(t))
df3 %>% ggvis(~x, ~y) %>% layer_paths()
df3 %>% ggvis(~x, ~y) %>% layer_lines()
- layer_histograms()and- layer_freqpolys()first bin the data with- compute_bin()and then display the results with either rects or lines.
mtcars %>% ggvis(~mpg) %>% layer_histograms(fill:= "red")
## Guessing width = 1 # range / 24
mtcars %>% ggvis(~mpg) %>% layer_freqpolys(fill:= "red")
## Guessing width = 1 # range / 24
- layer_smooths()fits a smooth model to the data, and displays predictions with a line
mtcars %>% ggvis(~wt, ~mpg) %>% layer_smooths()
Multiple layers
Like ggplot2 we can combine multiple layers together.
mtcars %>% ggvis(~wt, ~mpg) %>% layer_points %>% layer_smooths()
mtcars %>% ggvis(~wt, ~mpg) %>%
  layer_points %>% 
  layer_smooths(span = 1) %>%
  layer_smooths(span = 0.5, stroke := "red")
Scales
Scales, to control the mapping between data and visual properties. These are described in the properties and scales vignette
Legends
Legends and axes to control the appearance of the guides produced by the scales. See the axes and legends vignette for more details.
Basic interactivity
`input_slider()
mtcars %>% 
  ggvis(x = ~wt, y = ~mpg) %>% 
  layer_smooths(span = input_slider(0.5, 1, 1, label = "span")) %>% 
  layer_points(size := input_slider(100, 1000, label = "size"))
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_checkbox
mtcars %>% ggvis(~wt, ~mpg) %>%
  layer_smooths(se = input_checkbox(label = "Confidence interval", value = TRUE))
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_radiobuttons
  mtcars %>% ggvis(x = ~wt, y = ~mpg) %>%
  layer_points(
    fill := input_radiobuttons(
      choices = c("Red" = "red", "Green" = "green", "Blue" = "blue"),
      label = "Colors",
      selected = "red")
  )
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_checkboxgroup
  mtcars %>% ggvis(x = ~wt, y = ~mpg) %>%
  layer_points(
    fill := input_checkboxgroup(
      choices = c("Red" = "r", "Green" = "g", "Blue" = "b"),
      label = "Point color components",
      map = function(val) {
        rgb(0.8 * "r" %in% val, 0.8 * "g" %in% val, 0.8 * "b" %in% val)
      }
    )
  )
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_text()
fill_text <- input_text(label = "Point color", value = "dodgerblue")
mtcars %>% ggvis(~wt, ~mpg, fill := fill_text) %>% layer_points()
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_numeric()
size_num <- input_numeric(label = "Point size", value = 25)
mtcars %>% ggvis(~wt, ~mpg, size := size_num) %>% layer_points()
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
input_select()
iris %>% 
  ggvis(x = input_select(c('Petal.Width', 'Sepal.Length'), map = as.name)) %>% 
  layer_points(y = ~Petal.Length, fill = ~Species)
## Warning: Can't output dynamic/interactive ggvis plots in a knitr document.
## Generating a static (non-dynamic, non-interactive) version of the plot.
Outputting your ggvis plot
This is still in active development and is not especially user friendly. For more information, visit here
outfile <- iris %>% 
  ggvis(x = input_select(c('Petal.Width', 'Sepal.Length'), map = as.name)) %>% 
  layer_points(y = ~Petal.Length, fill = ~Species) %>%
  view_dynamic() %>% htmltools::html_print(viewer = NULL)
Some last notes on ggvis
ggvis is still actively being developed and there is a lot more detail than I have provided. In addition, there is still a lot that ggvis can not do. I encourage you to check out the ggvis website for more information and updates.
googleVis
The googleVis package provides an interface between R and the Google Charts API. Google Charts offer interactive charts which can be embedded into web pages.
There are many options for figures and given our time constraint, we will only cover a portion of what is available. I encourage you to look here and here for additional ideas and details.
# install.packages("googleVis")
library(googleVis)
## Creating a generic function for 'toJSON' from package 'jsonlite' in package 'googleVis'
## 
## Welcome to googleVis version 0.6.1
## 
## Please read the Google API Terms of Use
## before you start using the package:
## https://developers.google.com/terms/
## 
## Note, the plot method of googleVis will by default use
## the standard browser to display its output.
## 
## See the googleVis package vignettes for more details,
## or visit http://github.com/mages/googleVis.
## 
## To suppress this message use:
## suppressPackageStartupMessages(library(googleVis))
op <- options(gvis.plot.tag='chart')
To get these to work in RMarkdown you will need to specify results='asis' in the chunk options.
Line plots
df <- data.frame(time=c(1:70), 
              val1=c(1:70)*3 +rnorm(70, sd = 6), 
              val2=c(1:70)*5 +rnorm(70, sd = 10))
Line_plot <- gvisLineChart(df, xvar = "time", yvar = c("val1", "val2"))
plot(Line_plot)
Line_plot2 <- gvisLineChart(df, xvar = "time", yvar = c("val1", "val2"), options = list(series = "[{targetAxisIndex: 0}, {targetAxisIndex:1}]", 
    vAxes = "[{title:'val1'}, {title:'val2'}]"))
plot(Line_plot2)
Bar plots
mpg<-mtcars %>% 
    mutate(gear = paste("gear",gear,sep="_")) %>% 
    group_by(cyl, gear) %>% 
    summarise(M_mpg = mean(mpg)) %>% 
    spread(gear, M_mpg) %>% 
    as.data.frame()
mpg$gear_4[is.na(mpg$gear_4)] <-0
mpg_side <- gvisBarChart(data = mpg, xvar = c("cyl"), yvar = c("gear_3", "gear_4", 
    "gear_5"))
plot(mpg_side)
mpg_vert <- gvisColumnChart(data = mpg, xvar = c("cyl"), yvar = c("gear_3", 
    "gear_4", "gear_5"), options = list(title = "The mean mpg per cylinder", 
    colors = "['#cbb69d', '#603913', '#c69c6e']", vAxes = "[{title:'miles per gallon'}]", 
    hAxes = "[{title:'Number of cylinders'}]"))
plot(mpg_vert)
mpg_cars<-mtcars %>% 
    mutate(gear = paste("gear",gear,sep="_")) %>% 
    group_by(cyl, gear) %>% 
    summarise(N = n()) %>% 
    spread(gear, N) %>% 
    as.data.frame()
mpg$gear_4[is.na(mpg$gear_4)] <-0
mpg_stack <- gvisColumnChart(data = mpg, xvar = c("cyl"), yvar = c("gear_3", 
    "gear_4", "gear_5"), options = list(isStacked = TRUE, title = "The mean mpg per cylinder", 
    colors = "['#cbb69d', '#603913', '#c69c6e']", vAxes = "[{title:'Number of cars'}]", 
    hAxes = "[{title:'Number of cylinders'}]"))
plot(mpg_stack)
Area plots
df4 <- data.frame(Year = c(2013:2016), Sales = c(1000, 1170, 660, 1030), Expenses = c(400, 460, 1120, 540))
df4
##   Year Sales Expenses
## 1 2013  1000      400
## 2 2014  1170      460
## 3 2015   660     1120
## 4 2016  1030      540
Area <- gvisAreaChart(df4, xvar = "Year", yvar = c("Sales", "Expenses"))
plot(Area)
Area_stack <- gvisAreaChart(df4, xvar = "Year", yvar = c("Sales", "Expenses"), 
    options = list(isStacked = TRUE))
plot(Area_stack)
Combo plots
head(CityPopularity)
     City Popularity 1    New York        200 2      Boston        300 3       Miami        400 4     Chicago        500 5 Los Angeles        600 6     Houston        700
CityPopularity$Mean = mean(CityPopularity$Popularity)
CC <- gvisComboChart(CityPopularity, xvar = "City", yvar = c("Mean", "Popularity"), 
    options = list(seriesType = "bars", width = 450, height = 300, title = "City Popularity", 
        series = "{0: {type:\"line\"}}"))
plot(CC)
GeoChart plots
library(datasets)
states <- data.frame(state.name, state.x77)
head(states)
##            state.name Population Income Illiteracy Life.Exp Murder HS.Grad
## Alabama       Alabama       3615   3624        2.1    69.05   15.1    41.3
## Alaska         Alaska        365   6315        1.5    69.31   11.3    66.7
## Arizona       Arizona       2212   4530        1.8    70.55    7.8    58.1
## Arkansas     Arkansas       2110   3378        1.9    70.66   10.1    39.9
## California California      21198   5114        1.1    71.71   10.3    62.6
## Colorado     Colorado       2541   4884        0.7    72.06    6.8    63.9
##            Frost   Area
## Alabama       20  50708
## Alaska       152 566432
## Arizona       15 113417
## Arkansas      65  51945
## California    20 156361
## Colorado     166 103766
GeoStates <- gvisGeoChart(states, "state.name", "Murder", options = list(region = "US", 
    displayMode = "regions", resolution = "provinces", width = 600, height = 400, 
    colors = "['skyblue','red']"))
plot(GeoStates)
Interactive plots
Like using ggvis, you do have the option to make fully interactive plots.  You won’t be able to get it to work in the console or in Rstudio because googleVis creates  javascript that is embedded into an HTML document . The only way to know for sure if it’s working is to knit it to HTML, and then publish it to Rpubs (or anywhere else online). Once it is online it will work. Depending on your browser settings, you might be able to get it to work by opening the HTML locally, but the browser often blocks the embedded plot when opened locally
M <- gvisMotionChart(Fruits, "Fruit", "Year")
plot(M, 'chart')
Outputting googlevis plots
# write the HTML body to a temporary file without header and footer
cat(M$html$chart, file="/Users/cchizinski2/Documents/DataDepot/temp.html")