Nature, October 2014
16 June 2016
Nature, October 2014
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 \]
Shiny
library(shiny) runGitHub('ekstroem/ShinyLeastSquares')
The "role" of graphics is changing and expanding
directlabels
, animint
, plotly
, …MESS
, MethComp
, SuperRanker
, …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:
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")
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.
Numerous possibilities in R packages
htmlwidgets Javascript framework (many are part of this). Super important!
ggiraph (ggplot graphics interactive)
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 |
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")
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/linesguides
\(\approx\) axisaddParams
\(\approx\) title, plot sizer3 <- rPlot(x = "tax", y = "happy", data = mydf, type = "point", color = "continent", size = "size", tooltip="#!function(item){ return ('Country: ' +item.country+ '
 Tax: ' +item.tax+ '% Happiness: ' +item.happy+ '<br> Pop: ' +item.population+ ' mio.') }!#")
Passing javascript is non-trivial.
Mature charts, stocks (time series), maps. Good API.
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
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
)
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")) |
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
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") %>% ...
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
.
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
, …
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))
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")
Beautiful maps crated by adding layers on top of maps.
library(leaflet) m <- leaflet() %>% addTiles() %>% # Default OpenStreetMap map tiles addMarkers(lat=37.431106, lng=-122.164672, popup="useR 2016") m
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() |
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
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 )
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")
htmlwidget
widgets behave nicely in R markdown.
as.iframe
to appear.
Use ggplot2 (and grammar of graphics) to render interactive graphics.
Use legend to toggle traces, zoom, shift and click to pan. Super simple: p <- ggplot() ; ggplotly(p)
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)
Just works (automatically embedded)
Embed the graph as an iframe
signup("username", "email", save=TRUE) plotly_POST(p, "My Chart")
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.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")
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" )
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
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
library(shiny) runGitHub('ekstroem/ShinySampleMean')
"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 ) ))
Communication through input
and output
lists.
library(shiny) # Define server shinyServer(function(input, output) { output$something <- renderFunction( v1 <- input$variable1 # Get input ... ) })
checkboxInput
- Check boxdateInput
- Calendar to aid date selectiondateRangeInput
- Pair of calendars for selecting a date rangefileInput
- File upload control wizardnumericInput
- Field to enter numbersradioButtons
- Set of radio buttonsselectInput
- Box with choices to select fromsliderInput
- Slider bartextInput
- Text areahtmlOutput
- raw HTMLimageOutput
- imageplotOutput
- plottableOutput
- tabletextOutput
- textverbatimTextOutput
- textInput functions are strings
renderImage
- images (saved as a link to a source file)renderPlot
- plotsrenderPrint
- any printed outputrenderTable
- data frame, matrix, other table like structuresrenderText
- Raw textEach render*
function takes a single argument: an R expression surrounded by braces, {}.
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)
runGitHub("ekstroem/useRapp")
Try to run the code from previous example. Add a slider to change the point size in the graph.
sliderInput
(arguments: label, text, start value, min value, max value)