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 propertiesy
andy2
to 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
,y
andy2
properties.
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),dx
anddy
(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()
andlayer_freqpolys()
first bin the data withcompute_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")