16 June 2016

Why? Presenting research results

Nature, October 2014

Why? Teaching

Least squares estimation

Linear regression model

\[ y_i = \alpha + \beta x_i + \epsilon \]

Estimates for the intercept and slope can be found by minimizing the squared residuals.

\[ \arg\min_{\alpha, \beta} \sum_i \left(y_i - (\alpha + \beta x_i) \right)^2 \]





Why? Teaching

Why? Teaching

Why? Teaching

Why? Teaching

Shiny

library(shiny)
runGitHub('ekstroem/ShinyLeastSquares')

The "role" of graphics is changing and expanding

Background

Toby

  • Dept. Human Genetics, McGill University.
  • R packages: directlabels, animint, plotly, …
  • Animint book in progress https://github.com/tdhock/animint-book
  • Uses interactive graphics for machine learning model visualization.




Claus

  • Dept. Biostatistics, UCPH
  • R packages: MESS, MethComp, SuperRanker, …
  • R book: The R Primer
  • Happy/frustrated interactive graphics enthusiast

Outline for the tutorial

Topic
Introduction (10 min.)
Interactive graphics/javascript (htmlwidgets, 30 min)
Interactive graphics (ggplotly/ggiraph) 20 minutes
Shiny 20 minutes
Intro to animation and direct manipulation 5 minutes
Basics of ggplot2 and animint 25 minutes
aes(showSelected), animation 25 minutes
aes(clickSelects), direct manipulation 25 minutes




Tutorial goals:

  1. Explain and emphasize the role that interactive graphics have in reporting, scientific journals, and in teaching.
  2. Give overview of existing R packages for interactive graphics.
  3. Explain the strengths and weaknesses of the existing R packages, to highlight directions for future work.




Necessary stuff

CRANpackages <- c("MESS", "dplyr", "shiny", "plotly", "xts", "highcharter"
                  "DiagrammeR", "dygraphs", "ggplot2", "htmlwidgets",
                  "leaflet", "viridis")

install.packages(CRANpackages)

devtools::install_github('ramnathv/rCharts')

Or run

source("http://biostatistics.dk/useR2016pack.R")

The role of the graphics/viewer

Interactive graphics architechture

  • Distribution and viewing
  • Dedicated server vs. local server

Javascript-based libraries (htmlwidgets)

R and Javascript architecture

D3.js doesn’t ship with any pre-built charts out of the box. However, go to website to get an overview of the possibilities.

  • ChartJS
  • Chartist.js
  • [n3]
  • plotly

Highlevel interactive graphics

Numerous possibilities in R packages

  • rCharts (oldish - mix of libraries)
  • highcharter (standard plot types, mature library, maps, time series)
  • dygraphs (mostly time series. well documented. Rich features)
  • metricsgraphics (also time series)
  • leaflet (maps)
  • htmlwidgets Javascript framework (many are part of this). Super important!

  • plotly (general plots - like ggplot)
  • ggiraph (ggplot graphics interactive)



  • No standard interface
  • Not easily extendable from R
  • Pick a library and learn it!

rCharts interfaces

library R function Functionality
polychart rPlot ggplot2-like
Morris mPlot Pretty time series
nvd3 nPlot Lines/areas/bars
xCharts xPlot Various graphs
Highcharts hPlot Interactive charts
Leaflet new() Interactive Maps
Rickshaw new() Real-time ts graphs
Dimple dPlot Business analytics

polychart (from rCharts package)

plot/lattice-like function.

library(rCharts)
library(MESS)
data(happiness)
mydf <- happiness
mydf$size <- sqrt(mydf$population)/8
r1 <- rPlot(x = "tax",
            y = "happy",
            data = mydf,
            type = "point",
            color = "continent",
            size = "size")
r1

Type: point, bar, line, …

Add layers: r1$layer(y= ..., copy_layer=TRUE, type="line")

polychart (from rCharts package)

plot/lattice-like function. Add layers and guides to plot ..

mydf2 <- data.frame(tax=c(1, 50),
                happy=c(4.93, 7.09))

r1$layer(x = "tax",
         y = "happy",
         data = mydf2,
         type = "line",
         size=list(const=4))

r1$guides(y = list(title="New label",
                   min=0, max=12))

r1
  • layer \(\approx\) points/lines
  • guides \(\approx\) axis
  • addParams \(\approx\) title, plot size

polychart - tooltips

r3 <- rPlot(x = "tax", y = "happy",
      data = mydf, type = "point",
      color = "continent",
      size = "size",
      tooltip="#!function(item){
return ('Country: ' +item.country+
        '&#013; Tax: ' +item.tax+
        '% Happiness: ' +item.happy+
        '<br> Pop: ' +item.population+
        ' mio.') }!#")

Passing javascript is non-trivial.

Highcharts

HighCharter

highcharter (highcharter package)

Mature charts, stocks (time series), maps. Good API.

  • Start with empty chart and add components.
  • (Mostly) no default arguments
library(highcharter)
hc <- highchart() %>%
  hc_chart(type = "column") %>%
  hc_title(text = "Denmark") %>%
  hc_xAxis(categories = 2011:2016) %>%
  hc_add_series(data = c(3806,  6184,
                         7557, 14792,
                         21315, 3016),
          name = "Asylum seekers") %>%
  hc_add_serie(name = "Syria",
               data = c(429, 822,
                      1710, 7087,
                       8608, 777),
               type = "spline")
hc




highcharter - adding data

Data are added using one of the following functions

Name Function
hc_add_series Add single series (named: data, name)
hc_add_series_list Add list of named series
hc_add_series_df Add data.frame. Name variables accordingly => plot type
hc_add_series_ts Add and plot ts object. Extra argument: name
hc_add_series_scatter Create and plot scatter from two vectors. Extra arguments (size, color, label)
hc_add_series_boxplot Add and plot boxplots
hc_add_series_map Add geojson map

Chart types: line (default), column, boxplot, bubble, arearange, heatmap, funnel, pie, …

Also: the hchart function (a la plot)

Highcharter function overview

Function Example
Title, subtitle hc_title(text = "Temperature"), hc_subtitle(text = "Somewhere warm")
Axis hc_xAxis(categories = month)
hc_yAxis(title = list(text = "Temperature"), labels = list(format = "{value} C"))
Theme hc_add_theme(hc_theme_sandsignika())
Zoom hc_chart(zoomType = "xy")
Export hc_exporting(enabled = TRUE)
Tooltip hc_tooltip(useHTML = TRUE, headerFormat="<table>",
pointFormat = "<tr><th>x-val</th><td>{point.x}</td></tr>"
footerFormat = "</table>")
Legend hc_legend(enabled=FALSE)
Credits hc_credits(enabled = TRUE, text = "Source: Wikipedia", href = "https://wikipedia.com", style = list(fontSize = "12px"))

Highcharter - adding information

happiness$size <- sqrt(happiness$population)/8
hap <- happiness # Shorten name
happy2 <- highchart() %>%
  hc_title(text = "Taxes and happiness") %>%
  hc_subtitle(text = "Source: Wikipedia") %>%
  hc_xAxis(title = list(text = "Taxation (%)")) %>%
  hc_yAxis(title = list(text = "Happiness")) %>%
  hc_chart(zoomType = "xy") %>% hc_exporting(enabled = TRUE) %>%
  hc_add_serie_scatter(hap$tax, hap$happy, 
                       hap$size, hap$continent, hap$country,
                       dataLabels = list( enabled = TRUE,
                                    format = "{point.label}")) %>%
  hc_tooltip(useHTML = TRUE,
             headerFormat = "<table>",
             pointFormat = paste("<tr><th colspan=\"1\"><b>{point.label}</b></th></tr>",
                                 "<tr><th>Tax</th><td>{point.x} %</td></tr>",
                                 "<tr><th>Score</th><td>{point.y}</td></tr>",
                                 "<tr><th>Pop</th><td>{point.z} </td></tr>",
                                 "<tr><th>Cont.</th><td>{point.valuecolor} hp</td></tr>",
                                 "<tr><th>Religion</th><td>{point.extrainfo} hp</td></tr>"),
             footerFormat = "</table>")
happy2

Highcharter - adding information

Exercise

Take the airquality dataset. Plot series of temperature and wind speed for June using for example highcharter or polychart.

data(airquality)
aq <- subset(airquality, Month==6)
head(aq)

library(highcharter)
hc <- highchart() %>%
  hc_chart(type = "column") %>%
  hc_title(text = "Denmark") %>%
  hc_xAxis(categories = aq$Day) %>% 
  hc_add_series(data = aq$Temp,
          name = "Temperature") %>%
 ...

One solution

dygraphs

dygraphs

dygraphs

Same build-up as highcharter. Most of the information passed in dygraph and dyOptions.

xts extended time series

library(dygraphs)
library(MESS)
library(xts)
data(greenland)
rownames(greenland) <-
  paste0(greenland$year, "-07-15")
greenland$year <- NULL
temp <- as.xts(greenland)
dygraph(temp, 
        main="Av. Summer temp") %>%
  dyRangeSelector(dateWindow = 
      c("1960-01-01", "2011-01-01"))

Series can be added with dySeries.




dygraphs functions

Function Example
Title dygraph(data, main = "My Title")
Axis dyAxis("x", drawGrid = TRUE, label="My X axis")
Zoom/panning dyRangeSelector()
Highlights dyHighlight(highlightSeriesOpts = list(strokeWidth = 3))
dyOptions/dySeries Example
Step Plot dyOptions(stepPlot = TRUE)
Colour dyOptions(colors="blue")
Fill dyOptions(fillGraph = TRUE, fillAlpha = 0.4)
L/V/U A 3-vector name has special meaning (lower, value, upper). dySeries(c("L", "V", "U"))

Also: dyShading, dyEvent, …

dygraphs 2

Danish Monthly births/deaths. Multiple series.

library(MESS)
library(dygraphs)
data(bdstat)
births <- ts(bdstat$births[1:(12*112)], 
             frequency=12, 
             start=c(1901, 1)) 
deaths <- ts(bdstat$dead[1:(12*112)], 
             frequency=12, 
             start=c(1901, 1)) 
DKdata <- cbind(births, deaths)
dygraph(DKdata, 
        main="Births/Deaths") %>%
  dyAxis("x", drawGrid = FALSE) %>%
  dySeries("births", drawPoints=TRUE, 
           color = "blue") %>%
  dySeries("deaths", stepPlot = TRUE, 
           fillGraph = TRUE, 
           color = "red") %>%
  dyHighlight(highlightSeriesOpts = 
              list(strokeWidth = 3)) 





dygraphs 3

Danish Monthly births/deaths. Multiple series. Prediciton

dkb <- HoltWinters(births)
p <- predict(dkb, n.ahead = 50*12, 
             prediction.interval=TRUE)
all <- cbind(births, p)

dygraph(all, main = "Births (DK)") %>%
  dySeries("births", drawPoints = TRUE, 
           color = "blue", 
           label="asd") %>%
  dySeries(c("p.lwr","p.fit","p.upr"),
           color = "red")










leaflet

The leaflet package

Beautiful maps crated by adding layers on top of maps.

leaflet example

library(leaflet)

m <- leaflet() %>%
  addTiles() %>%  # Default OpenStreetMap map tiles
  addMarkers(lat=37.431106, lng=-122.164672, popup="useR 2016") 
m 

leaflet function overview

Main functions

Function Example
Default map addTiles()
Alternative maps addProviderTiles("CartoDB.DarkMatter", options = providerTileOptions(opacity = 0.35)) Stackable!
Markers addMarkers(~long, ~lat, popup = ~as.character(mag))
Pop-ups addPopups(lng=-122.164672, lat=37.431106, "<a href='http://www.user2016.org'> Hi </a>", options = popupOptions(closeButton = FALSE))
Custom icons makeIcon()

Earthquakes

library(leaflet)
library(MESS)

pal <- colorNumeric("RdYlBu", 
                    domain = NULL)
data(earthquakes)
m <- leaflet(subset(earthquakes,  mag>3)) %>%
  addProviderTiles("CartoDB.DarkMatter") %>%  
addCircleMarkers(
    radius = ~ mag*3,
    color  = ~ pal(depth),
    stroke = FALSE, fillOpacity = 0.4
  )
m

Earthquakes

Exercise

Create your own icon and pop-up on this map.

library(leaflet)
m <- leaflet() %>%
  addTiles() %>%  # Default OpenStreetMap map tiles
  addMarkers(lng=-122.164672, lat=37.431106, popup="useR 2016") 
m 

Add the R icon to the map: https://www.r-project.org/logo/Rlogo.png (Use icon instead of popup in addMarkers). Create simple icon:

greenLeafIcon <- makeIcon(
  iconUrl = "http://leafletjs.com/docs/images/leaf-green.png",
  iconWidth = 38, iconHeight = 95,
  iconAnchorX = 22, iconAnchorY = 94
)

Publishing interactive graphics

Note: html/js output. Need javascript machinery to run (ie., html with js code embedded or online link).

library(htmlwidgets)
saveWidget(widget, file, selfcontained = TRUE, background="white")

Including in R markdown

htmlwidget widgets behave nicely in R markdown.

Otherwise

as.iframe to appear.

Javascript-based libraries (ggplotly and ggiraph)

ggplotly and ggiraph

Use ggplot2 (and grammar of graphics) to render interactive graphics.

  • ggplotly use the plot.ly service
  • ggiraph uses it's own htmlwidget extensions.

Plotly - ggplotly

plotly

The plotly package

Use legend to toggle traces, zoom, shift and click to pan. Super simple: p <- ggplot() ; ggplotly(p)

Revisiting the happiness data

library(ggplot2)
library(plotly)

p <- ggplot(happiness, 
            aes(x=tax, y=happy, color=continent, size=population, 
                text = paste("country:", country))) + 
  geom_point( alpha = I(0.8)) + 
  scale_size_area(max_size = 30) + 
  geom_smooth(method="lm", se= F, size = 1, 
              aes(linetype = continent, group = continent))
ggplotly(p)

Revisiting the happiness data

Publishing ggplotly graphics

Works directly in R markdown / knitr

Just works (automatically embedded)

Post on plot.ly account

Embed the graph as an iframe

signup("username", "email", save=TRUE)
plotly_POST(p, "My Chart")

The ggiraph package

Extends ggplot2 with new geom functions.

  • geom_point_interactive, geom_polygon_interactive, geom_map_interactive, geom_path_interactive, geom_rect_interactive, geom_segment_interactive, geom_text_interactive

Three arguments let you add interactivity:

  • tooltip: mouse-over tooltips to be displayed when mouse is over elements.
  • onclick: javascript function to be executed when elements are clicked.
  • data_id: id to be associated with elements.

ggiraph example - happiness

library(ggiraph)

happiness$tooltip <- paste0("<table><th>Welcome to</th><tr><td>", 
                            happiness$country, 
                            "</td></tr></table>")

p <- ggplot(happiness, 
            aes(x=tax, y=happy, color=continent, 
                size=population, tooltip=tooltip)) + 
  geom_point_interactive(alpha=I(.8)) + 
  scale_size_area(max_size = 30)

ggiraph(code = {print(p)}, height = "350px")

ggiraph example - happiness

ggiraph and dataid and onclick events

library(ggiraph)

happiness$tooltip <- paste0("<table><th>Welcome to</th><tr><td>", happiness$country, "</td></tr></table>")

happiness$onclick <- sprintf(
  "window.open(\"%s%s\")",
  "http://en.wikipedia.org/wiki/",
  as.character(happiness$country)
)

happiness$data_id <- happiness$country

p3 <- ggplot(happiness, 
            aes(x=tax, y=happy, color=continent, 
                size=population, tooltip=tooltip, 
                onclick=onclick, data_id=data_id)) + 
  geom_point_interactive(alpha=I(.8)) + 
  scale_size_area(max_size = 30)

ggiraph(code = print(p3), 
        hover_css = "fill-opacity:.3;cursor:pointer;",  # data_id 
        width="600px", height = "300px"
)

ggiraph and dataid and onclick events

Exercise

Use ggplotly/ggiraph to create an interactive plot of development in average Danish life expectancy for males and females.

library(MESS)
data(lifeexpect)
head(lifeexpect)
##        year male female  myear
## 1 1840:1849 42.9   45.0 1844.5
## 2 1850:1859 43.1   45.4 1854.5
## 3 1860:1869 43.7   45.6 1864.5
## 4 1870:1879 45.5   47.2 1874.5
## 5 1880:1889 46.8   48.9 1884.5
## 6 1890:1900 48.6   51.4 1895.0


Could start with

library(ggiraph)
p <- ggplot(lifeexpect, 
            aes(x=myear, y=male)) + 
     geom_path()
p

Shiny

Shiny

Use standard R. Rather simple and beautiful. Requires server, or running locally in R.

Two files

  Directory
  |
  +-- ui.R
  +-- server.R

Or single file, app.R, with

server <- function(input, output) { ... }
ui <- fluidPage( ...)

shinyApp(ui = ui, server = server)

Run using

library(shiny)
runApp("/path/to/directory")           # Local
runGitHub('ekstroem/ShinySampleMean')  # From GitHub

Example

library(shiny)
runGitHub('ekstroem/ShinySampleMean')

Shiny User Interface

"Standard" design layout with sidebar for input and main window for output.

library(shiny)

shinyUI(pageWithSidebar(
  
  titlePanel("My title"), # Application title

  sidebarLayout(          # Layout for this page
    sidebarPanel(         # Well a side bar panel
      selectInput()       # Input type
    ),  
    mainPanel(
      plotOutput()        # Types of output
    )                     # ... and main panel
  )
))

Shiny server interface

Communication through input and output lists.

library(shiny)

# Define server 
shinyServer(function(input, output) {
  
  output$something <- renderFunction( 
    v1 <- input$variable1 # Get input
    ... 
    )
})

User interface functions

Inputs

  • checkboxInput - Check box
  • dateInput - Calendar to aid date selection
  • dateRangeInput - Pair of calendars for selecting a date range
  • fileInput - File upload control wizard
  • numericInput - Field to enter numbers
  • radioButtons - Set of radio buttons
  • selectInput - Box with choices to select from
  • sliderInput - Slider bar
  • textInput - Text area

Outputs

  • htmlOutput - raw HTML
  • imageOutput - image
  • plotOutput - plot
  • tableOutput - table
  • textOutput - text
  • verbatimTextOutput - text

Server side functions

Input functions are strings

  • renderImage - images (saved as a link to a source file)
  • renderPlot - plots
  • renderPrint - any printed output
  • renderTable - data frame, matrix, other table like structures
  • renderText - Raw text

Each render* function takes a single argument: an R expression surrounded by braces, {}.

Example

library(shiny)

ui <- fluidPage(
  titlePanel("My title"),
  sidebarLayout(
      sidebarPanel(
      selectInput("xvar", label = h3("Select x"),
                  choices = list("A"=1, "B"=2, "C"=3),
            selected = 1)),
    mainPanel(
      textOutput("text"),
      plotOutput("plot", height="600")
    )))

server <- function(input, output) {
    output$plot <- renderPlot({
        mytext <- input$xvar
        hist(rnorm(1000), col="lightred")
    })
    output$text <- renderText( { paste0("Hello ", mytext) } )
}

shinyApp(ui = ui, server = server)

Example - view data frame

runGitHub("ekstroem/useRapp")

Exercise

Try to run the code from previous example. Add a slider to change the point size in the graph.

  1. Look at the code
  2. Add sliderInput (arguments: label, text, start value, min value, max value)
  3. Change server function to accommodate the new input